#include "RegistersView.h"

#include <stdint.h>

#include <QListWidget>
#include <QMessageBox>
#include <QToolTip>

#include "CPUDisassembly.h"
#include "CPUMultiDump.h"
#include "Configuration.h"
#include "EditFloatRegister.h"
#include "LineEditDialog.h"
#include "MiscUtil.h"
#include "SelectFields.h"
#include "WordEditDialog.h"
#include "ldconvert.h"

int RegistersViewA64::getEstimateHeight() { return mRowsNeeded * mRowHeight; }

void RegistersViewA64::SetChangeButton(QPushButton* push_button) {
  mChangeViewButton = push_button;
  fontsUpdatedSlot();
}

void RegistersViewA64::InitMappings() {
  // create mapping from internal id to name
  mRegisterMapping.clear();
  mRegisterPlaces.clear();
  mRegisterRelativePlaces.clear();
  int offset = 0;

  /* Register_Position is a struct definition the position
   *
   * (line , start, labelwidth, valuesize )
   */
#ifdef _WIN64
#if 0
    mRegisterMapping.insert(CAX, "RAX");
    mRegisterPlaces.insert(CAX, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CAX, Register_Relative_Position(UNKNOWN, CBX));
    mRegisterMapping.insert(CBX, "RBX");
    mRegisterPlaces.insert(CBX, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CBX, Register_Relative_Position(CAX, CCX));
    mRegisterMapping.insert(CCX, "RCX");
    mRegisterPlaces.insert(CCX, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CCX, Register_Relative_Position(CBX, CDX));
    mRegisterMapping.insert(CDX, "RDX");
    mRegisterPlaces.insert(CDX, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CDX, Register_Relative_Position(CCX, CBP));
    mRegisterMapping.insert(CBP, "RBP");
    mRegisterPlaces.insert(CBP, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CBP, Register_Relative_Position(CDX, CSP));
    mRegisterMapping.insert(CSP, "RSP");
    mRegisterPlaces.insert(CSP, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CSP, Register_Relative_Position(CBP, CSI));
    mRegisterMapping.insert(CSI, "RSI");
    mRegisterPlaces.insert(CSI, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CSI, Register_Relative_Position(CSP, CDI));
    mRegisterMapping.insert(CDI, "RDI");
    mRegisterPlaces.insert(CDI, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CDI, Register_Relative_Position(CSI, R8));

    offset++;

    mRegisterMapping.insert(R8, "R8");
    mRegisterPlaces.insert(R8, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R8, Register_Relative_Position(CDI, R9));
    mRegisterMapping.insert(R9, "R9");
    mRegisterPlaces.insert(R9, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R9, Register_Relative_Position(R8, R10));
    mRegisterMapping.insert(R10, "R10");
    mRegisterPlaces.insert(R10, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R10, Register_Relative_Position(R9, R11));
    mRegisterMapping.insert(R11, "R11");
    mRegisterPlaces.insert(R11, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R11, Register_Relative_Position(R10, R12));
    mRegisterMapping.insert(R12, "R12");
    mRegisterPlaces.insert(R12, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R12, Register_Relative_Position(R11, R13));
    mRegisterMapping.insert(R13, "R13");
    mRegisterPlaces.insert(R13, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R13, Register_Relative_Position(R12, R14));
    mRegisterMapping.insert(R14, "R14");
    mRegisterPlaces.insert(R14, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R14, Register_Relative_Position(R13, R15));
    mRegisterMapping.insert(R15, "R15");
    mRegisterPlaces.insert(R15, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(R15, Register_Relative_Position(R14, CIP));
#else
  int i = 0;
  for (; i < 30; i++) {
    char regname[16];
    sprintf(regname, "x%d", i);
    mRegisterMapping.insert(i, regname);
    mRegisterPlaces.insert(
        i, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(
        i, Register_Relative_Position(i ? i - 1 : UNKNOWN, i + 1));
  }
  mRegisterMapping.insert(i, "lr");
  mRegisterPlaces.insert(i,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
  mRegisterMapping.insert(i, "sp");
  mRegisterPlaces.insert(i,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
#endif

  offset++;

#if 0
    mRegisterMapping.insert(CIP, "RIP");
    mRegisterPlaces.insert(CIP, Register_Position(offset++, 0, 6, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(CIP, Register_Relative_Position(R15, EFLAGS));
#else
  mRegisterMapping.insert(i, "pc");
  mRegisterPlaces.insert(i,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
#endif

  offset++;

#if 0
    mRegisterMapping.insert(EFLAGS, "RFLAGS");
    mRegisterPlaces.insert(EFLAGS, Register_Position(offset++, 0, 9, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(EFLAGS, Register_Relative_Position(CIP, ZF));
#else
  mRegisterMapping.insert(i, "flags");
  mRegisterPlaces.insert(i,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
#endif
#else  // x32
  mRegisterMapping.insert(CAX, "EAX");
  mRegisterPlaces.insert(CAX,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CAX, Register_Relative_Position(UNKNOWN, CBX));
  mRegisterMapping.insert(CBX, "EBX");
  mRegisterPlaces.insert(CBX,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CBX, Register_Relative_Position(CAX, CCX));
  mRegisterMapping.insert(CCX, "ECX");
  mRegisterPlaces.insert(CCX,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CCX, Register_Relative_Position(CBX, CDX));
  mRegisterMapping.insert(CDX, "EDX");
  mRegisterPlaces.insert(CDX,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CDX, Register_Relative_Position(CCX, CBP));
  mRegisterMapping.insert(CBP, "EBP");
  mRegisterPlaces.insert(CBP,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CBP, Register_Relative_Position(CDX, CSP));
  mRegisterMapping.insert(CSP, "ESP");
  mRegisterPlaces.insert(CSP,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CSP, Register_Relative_Position(CBP, CSI));
  mRegisterMapping.insert(CSI, "ESI");
  mRegisterPlaces.insert(CSI,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CSI, Register_Relative_Position(CSP, CDI));
  mRegisterMapping.insert(CDI, "EDI");
  mRegisterPlaces.insert(CDI,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CDI, Register_Relative_Position(CSI, CIP));

  offset++;

  mRegisterMapping.insert(CIP, "EIP");
  mRegisterPlaces.insert(CIP,
                         Register_Position(offset++, 0, 6, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(CIP, Register_Relative_Position(CDI, EFLAGS));

  offset++;

  mRegisterMapping.insert(EFLAGS, "EFLAGS");
  mRegisterPlaces.insert(EFLAGS,
                         Register_Position(offset++, 0, 9, sizeof(duint) * 2));
  mRegisterRelativePlaces.insert(EFLAGS, Register_Relative_Position(CIP, ZF));
#endif

#if 0
    mRegisterMapping.insert(ZF, "ZF");
    mRegisterPlaces.insert(ZF, Register_Position(offset, 0, 3, 1));
    mRegisterRelativePlaces.insert(ZF, Register_Relative_Position(EFLAGS, PF, EFLAGS, OF));
    mRegisterMapping.insert(PF, "PF");
    mRegisterPlaces.insert(PF, Register_Position(offset, 6, 3, 1));
    mRegisterRelativePlaces.insert(PF, Register_Relative_Position(ZF, AF, EFLAGS, SF));
    mRegisterMapping.insert(AF, "AF");
    mRegisterPlaces.insert(AF, Register_Position(offset++, 12, 3, 1));
    mRegisterRelativePlaces.insert(AF, Register_Relative_Position(PF, OF, EFLAGS, DF));

    mRegisterMapping.insert(OF, "OF");
    mRegisterPlaces.insert(OF, Register_Position(offset, 0, 3, 1));
    mRegisterRelativePlaces.insert(OF, Register_Relative_Position(AF, SF, ZF, CF));
    mRegisterMapping.insert(SF, "SF");
    mRegisterPlaces.insert(SF, Register_Position(offset, 6, 3, 1));
    mRegisterRelativePlaces.insert(SF, Register_Relative_Position(OF, DF, PF, TF));
    mRegisterMapping.insert(DF, "DF");
    mRegisterPlaces.insert(DF, Register_Position(offset++, 12, 3, 1));
    mRegisterRelativePlaces.insert(DF, Register_Relative_Position(SF, CF, AF, IF));

    mRegisterMapping.insert(CF, "CF");
    mRegisterPlaces.insert(CF, Register_Position(offset, 0, 3, 1));
    mRegisterRelativePlaces.insert(CF, Register_Relative_Position(DF, TF, OF, LastError));
    mRegisterMapping.insert(TF, "TF");
    mRegisterPlaces.insert(TF, Register_Position(offset, 6, 3, 1));
    mRegisterRelativePlaces.insert(TF, Register_Relative_Position(CF, IF, SF, LastError));
    mRegisterMapping.insert(IF, "IF");
    mRegisterPlaces.insert(IF, Register_Position(offset++, 12, 3, 1));
    mRegisterRelativePlaces.insert(IF, Register_Relative_Position(TF, LastError, DF, LastError));

    offset++;

    mRegisterMapping.insert(LastError, "LastError");
    mRegisterPlaces.insert(LastError, Register_Position(offset++, 0, 11, 20));
    mRegisterRelativePlaces.insert(LastError, Register_Relative_Position(IF, LastStatus));
    mMODIFYDISPLAY.insert(LastError);
    mRegisterMapping.insert(LastStatus, "LastStatus");
    mRegisterPlaces.insert(LastStatus, Register_Position(offset++, 0, 11, 20));
    mRegisterRelativePlaces.insert(LastStatus, Register_Relative_Position(LastError, GS));
    mMODIFYDISPLAY.insert(LastStatus);

    offset++;

    mRegisterMapping.insert(GS, "GS");
    mRegisterPlaces.insert(GS, Register_Position(offset, 0, 3, 4));
    mRegisterRelativePlaces.insert(GS, Register_Relative_Position(LastStatus, FS, LastStatus, ES));
    mRegisterMapping.insert(FS, "FS");
    mRegisterPlaces.insert(FS, Register_Position(offset++, 9, 3, 4));
    mRegisterRelativePlaces.insert(FS, Register_Relative_Position(GS, ES, LastStatus, DS));
    mRegisterMapping.insert(ES, "ES");
    mRegisterPlaces.insert(ES, Register_Position(offset, 0, 3, 4));
    mRegisterRelativePlaces.insert(ES, Register_Relative_Position(FS, DS, GS, CS));
    mRegisterMapping.insert(DS, "DS");
    mRegisterPlaces.insert(DS, Register_Position(offset++, 9, 3, 4));
    mRegisterRelativePlaces.insert(DS, Register_Relative_Position(ES, CS, FS, SS));
    mRegisterMapping.insert(CS, "CS");
    mRegisterPlaces.insert(CS, Register_Position(offset, 0, 3, 4));
    mRegisterMapping.insert(SS, "SS");
    mRegisterPlaces.insert(SS, Register_Position(offset++, 9, 3, 4));
#else
  mRegisterMapping.insert(i, "N");
  mRegisterPlaces.insert(i, Register_Position(offset, 0, 3, 1));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
  mRegisterMapping.insert(i, "Z");
  mRegisterPlaces.insert(i, Register_Position(offset, 6, 3, 1));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
  mRegisterMapping.insert(i, "C");
  mRegisterPlaces.insert(i, Register_Position(offset, 12, 3, 1));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
  mRegisterMapping.insert(i, "V");
  mRegisterPlaces.insert(i, Register_Position(offset++, 18, 3, 1));
  mRegisterRelativePlaces.insert(i, Register_Relative_Position(i - 1, i + 1));
  i++;
#endif

  if (mShowFpu) {
    REGISTER_NAME tempRegisterName;
    offset++;

    if (mFpuMode == 1) {
#if 0
            tempRegisterName = x87r0;

            mRegisterMapping.insert(x87r0, "x87r0");
            mRegisterPlaces.insert(x87r0, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r0, Register_Relative_Position(SS, x87r1));
            mRegisterMapping.insert(x87r1, "x87r1");
            mRegisterPlaces.insert(x87r1, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r1, Register_Relative_Position(x87r0, x87r2));
            mRegisterMapping.insert(x87r2, "x87r2");
            mRegisterPlaces.insert(x87r2, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r2, Register_Relative_Position(x87r1, x87r3));
            mRegisterMapping.insert(x87r3, "x87r3");
            mRegisterPlaces.insert(x87r3, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r3, Register_Relative_Position(x87r2, x87r4));
            mRegisterMapping.insert(x87r4, "x87r4");
            mRegisterPlaces.insert(x87r4, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r4, Register_Relative_Position(x87r3, x87r5));
            mRegisterMapping.insert(x87r5, "x87r5");
            mRegisterPlaces.insert(x87r5, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r5, Register_Relative_Position(x87r4, x87r6));
            mRegisterMapping.insert(x87r6, "x87r6");
            mRegisterPlaces.insert(x87r6, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r6, Register_Relative_Position(x87r5, x87r7));
            mRegisterMapping.insert(x87r7, "x87r7");
            mRegisterPlaces.insert(x87r7, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87r7, Register_Relative_Position(x87r6, x87TagWord));
#endif

    } else if (mFpuMode == 0) {
#if 0
            tempRegisterName = x87st0;

            mRegisterMapping.insert(x87st0, "ST(0)");
            mRegisterPlaces.insert(x87st0, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st0, Register_Relative_Position(SS, x87st1));
            mRegisterMapping.insert(x87st1, "ST(1)");
            mRegisterPlaces.insert(x87st1, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st1, Register_Relative_Position(x87st0, x87st2));
            mRegisterMapping.insert(x87st2, "ST(2)");
            mRegisterPlaces.insert(x87st2, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st2, Register_Relative_Position(x87st1, x87st3));
            mRegisterMapping.insert(x87st3, "ST(3)");
            mRegisterPlaces.insert(x87st3, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st3, Register_Relative_Position(x87st2, x87st4));
            mRegisterMapping.insert(x87st4, "ST(4)");
            mRegisterPlaces.insert(x87st4, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st4, Register_Relative_Position(x87st3, x87st5));
            mRegisterMapping.insert(x87st5, "ST(5)");
            mRegisterPlaces.insert(x87st5, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st5, Register_Relative_Position(x87st4, x87st6));
            mRegisterMapping.insert(x87st6, "ST(6)");
            mRegisterPlaces.insert(x87st6, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st6, Register_Relative_Position(x87st5, x87st7));
            mRegisterMapping.insert(x87st7, "ST(7)");
            mRegisterPlaces.insert(x87st7, Register_Position(offset++, 0, 6, 10 * 2));
            mRegisterRelativePlaces.insert(x87st7, Register_Relative_Position(x87st6, x87TagWord));
#endif

    } else if (mFpuMode == 2) {
#if 0
            tempRegisterName = MM0;

            mRegisterMapping.insert(MM0, "MM0");
            mRegisterPlaces.insert(MM0, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM0, Register_Relative_Position(SS, MM1));
            mRegisterMapping.insert(MM1, "MM1");
            mRegisterPlaces.insert(MM1, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM1, Register_Relative_Position(MM0, MM2));
            mRegisterMapping.insert(MM2, "MM2");
            mRegisterPlaces.insert(MM2, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM2, Register_Relative_Position(MM1, MM3));
            mRegisterMapping.insert(MM3, "MM3");
            mRegisterPlaces.insert(MM3, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM3, Register_Relative_Position(MM2, MM4));
            mRegisterMapping.insert(MM4, "MM4");
            mRegisterPlaces.insert(MM4, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM4, Register_Relative_Position(MM3, MM5));
            mRegisterMapping.insert(MM5, "MM5");
            mRegisterPlaces.insert(MM5, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM5, Register_Relative_Position(MM4, MM6));
            mRegisterMapping.insert(MM6, "MM6");
            mRegisterPlaces.insert(MM6, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM6, Register_Relative_Position(MM5, MM7));
            mRegisterMapping.insert(MM7, "MM7");
            mRegisterPlaces.insert(MM7, Register_Position(offset++, 0, 4, 8 * 2));
            mRegisterRelativePlaces.insert(MM7, Register_Relative_Position(MM6, x87TagWord));
#else
      for (int j = 0; j < 32; j++) {
        char regname[16];
        sprintf(regname, "q%d", j);
        mRegisterMapping.insert(i, regname);
        mRegisterPlaces.insert(i, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(
            i, Register_Relative_Position(i - 1, i + 1));
        i++;
      }
#endif
    }
#if 0
        mRegisterRelativePlaces.insert(CS, Register_Relative_Position(DS, SS, ES, tempRegisterName));
        mRegisterRelativePlaces.insert(SS, Register_Relative_Position(CS, tempRegisterName, DS, tempRegisterName));

        offset++;

        mRegisterMapping.insert(x87TagWord, "x87TagWord");
        mRegisterPlaces.insert(x87TagWord, Register_Position(offset++, 0, 11, sizeof(WORD) * 2));

        switch(mFpuMode)
        {
        case 0:
            tempRegisterName = x87st7;
            break;
        case 1:
            tempRegisterName = x87r7;
            break;
        case 2:
            tempRegisterName = MM7;
            break;
        }
        mRegisterRelativePlaces.insert(x87TagWord, Register_Relative_Position(tempRegisterName, x87TW_0));

        //Special treatment of long internationalized string
        int NextColumnPosition = 20;
        int temp;
        QFontMetrics metrics(font());
        //13 = 20 - strlen("Nonzero")
        temp = metrics.width(QApplication::translate("RegistersViewA64_ConstantsOfRegisters", "Nonzero")) / mCharWidth + 13;
        NextColumnPosition = std::max(NextColumnPosition, temp);
        temp = metrics.width(QApplication::translate("RegistersViewA64_ConstantsOfRegisters", "Zero")) / mCharWidth + 13;
        NextColumnPosition = std::max(NextColumnPosition, temp);
        temp = metrics.width(QApplication::translate("RegistersViewA64_ConstantsOfRegisters", "Special")) / mCharWidth + 13;
        NextColumnPosition = std::max(NextColumnPosition, temp);
        temp = metrics.width(QApplication::translate("RegistersViewA64_ConstantsOfRegisters", "Empty")) / mCharWidth + 13;
        NextColumnPosition = std::max(NextColumnPosition, temp);
        mRegisterMapping.insert(x87TW_0, "x87TW_0");
        mRegisterPlaces.insert(x87TW_0, Register_Position(offset, 0, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_0, Register_Relative_Position(x87TagWord, x87TW_1, x87TagWord, x87TW_2));
        mRegisterMapping.insert(x87TW_1, "x87TW_1");
        mRegisterPlaces.insert(x87TW_1, Register_Position(offset++, NextColumnPosition, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_1, Register_Relative_Position(x87TW_0, x87TW_2, x87TagWord, x87TW_3));

        mRegisterMapping.insert(x87TW_2, "x87TW_2");
        mRegisterPlaces.insert(x87TW_2, Register_Position(offset, 0, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_2, Register_Relative_Position(x87TW_1, x87TW_3, x87TW_0, x87TW_4));
        mRegisterMapping.insert(x87TW_3, "x87TW_3");
        mRegisterPlaces.insert(x87TW_3, Register_Position(offset++, NextColumnPosition, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_3, Register_Relative_Position(x87TW_2, x87TW_4, x87TW_1, x87TW_5));

        mRegisterMapping.insert(x87TW_4, "x87TW_4");
        mRegisterPlaces.insert(x87TW_4, Register_Position(offset, 0, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_4, Register_Relative_Position(x87TW_3, x87TW_5, x87TW_2, x87TW_6));
        mRegisterMapping.insert(x87TW_5, "x87TW_5");
        mRegisterPlaces.insert(x87TW_5, Register_Position(offset++, NextColumnPosition, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_5, Register_Relative_Position(x87TW_4, x87TW_6, x87TW_3, x87TW_7));

        mRegisterMapping.insert(x87TW_6, "x87TW_6");
        mRegisterPlaces.insert(x87TW_6, Register_Position(offset, 0, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_6, Register_Relative_Position(x87TW_5, x87TW_7, x87TW_4, x87StatusWord));
        mRegisterMapping.insert(x87TW_7, "x87TW_7");
        mRegisterPlaces.insert(x87TW_7, Register_Position(offset++, NextColumnPosition, 8, 10));
        mRegisterRelativePlaces.insert(x87TW_7, Register_Relative_Position(x87TW_6, x87StatusWord, x87TW_5, x87StatusWord));


        offset++;

        mRegisterMapping.insert(x87StatusWord, "x87StatusWord");
        mRegisterPlaces.insert(x87StatusWord, Register_Position(offset++, 0, 14, sizeof(WORD) * 2));
        mRegisterRelativePlaces.insert(x87StatusWord, Register_Relative_Position(x87TW_7, x87SW_B));

        mRegisterMapping.insert(x87SW_B, "x87SW_B");
        mRegisterPlaces.insert(x87SW_B, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87SW_B, Register_Relative_Position(x87StatusWord, x87SW_C3, x87StatusWord, x87SW_C1));
        mRegisterMapping.insert(x87SW_C3, "x87SW_C3");
        mRegisterPlaces.insert(x87SW_C3, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_C3, Register_Relative_Position(x87SW_B, x87SW_C2, x87StatusWord, x87SW_C0));
        mRegisterMapping.insert(x87SW_C2, "x87SW_C2");
        mRegisterPlaces.insert(x87SW_C2, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_C2, Register_Relative_Position(x87SW_C3, x87SW_C1, x87StatusWord, x87SW_ES));

        mRegisterMapping.insert(x87SW_C1, "x87SW_C1");
        mRegisterPlaces.insert(x87SW_C1, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87SW_C1, Register_Relative_Position(x87SW_C2, x87SW_C0, x87SW_B, x87SW_SF));
        mRegisterMapping.insert(x87SW_C0, "x87SW_C0");
        mRegisterPlaces.insert(x87SW_C0, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_C0, Register_Relative_Position(x87SW_C1, x87SW_ES, x87SW_C3, x87SW_P));
        mRegisterMapping.insert(x87SW_ES, "x87SW_ES");
        mRegisterPlaces.insert(x87SW_ES, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_ES, Register_Relative_Position(x87SW_C0, x87SW_SF, x87SW_C2, x87SW_U));

        mRegisterMapping.insert(x87SW_SF, "x87SW_SF");
        mRegisterPlaces.insert(x87SW_SF, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87SW_SF, Register_Relative_Position(x87SW_ES, x87SW_P, x87SW_C1, x87SW_O));
        mRegisterMapping.insert(x87SW_P, "x87SW_P");
        mRegisterPlaces.insert(x87SW_P, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_P, Register_Relative_Position(x87SW_SF, x87SW_U, x87SW_C0, x87SW_Z));
        mRegisterMapping.insert(x87SW_U, "x87SW_U");
        mRegisterPlaces.insert(x87SW_U, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_U, Register_Relative_Position(x87SW_P, x87SW_O, x87SW_ES, x87SW_D));

        mRegisterMapping.insert(x87SW_O, "x87SW_O");
        mRegisterPlaces.insert(x87SW_O, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87SW_O, Register_Relative_Position(x87SW_U, x87SW_Z, x87SW_SF, x87SW_I));
        mRegisterMapping.insert(x87SW_Z, "x87SW_Z");
        mRegisterPlaces.insert(x87SW_Z, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_Z, Register_Relative_Position(x87SW_O, x87SW_D, x87SW_P, x87SW_TOP));
        mRegisterMapping.insert(x87SW_D, "x87SW_D");
        mRegisterPlaces.insert(x87SW_D, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(x87SW_D, Register_Relative_Position(x87SW_Z, x87SW_I, x87SW_U, x87SW_TOP));

        mRegisterMapping.insert(x87SW_I, "x87SW_I");
        mRegisterPlaces.insert(x87SW_I, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87SW_I, Register_Relative_Position(x87SW_D, x87SW_TOP, x87SW_O, x87ControlWord));
        mRegisterMapping.insert(x87SW_TOP, "x87SW_TOP");
        mRegisterPlaces.insert(x87SW_TOP, Register_Position(offset++, 12, 10, 13));
        mRegisterRelativePlaces.insert(x87SW_TOP, Register_Relative_Position(x87SW_I, x87ControlWord, x87SW_Z, x87ControlWord));

        offset++;

        mRegisterMapping.insert(x87ControlWord, "x87ControlWord");
        mRegisterPlaces.insert(x87ControlWord, Register_Position(offset++, 0, 15, sizeof(WORD) * 2));
        mRegisterRelativePlaces.insert(x87ControlWord, Register_Relative_Position(x87SW_TOP, x87CW_IC));

        mRegisterMapping.insert(x87CW_IC, "x87CW_IC");
        mRegisterPlaces.insert(x87CW_IC, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87CW_IC, Register_Relative_Position(x87ControlWord, x87CW_ZM, x87ControlWord, x87CW_UM));
        mRegisterMapping.insert(x87CW_ZM, "x87CW_ZM");
        mRegisterPlaces.insert(x87CW_ZM, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87CW_ZM, Register_Relative_Position(x87CW_IC, x87CW_PM, x87ControlWord, x87CW_OM));
        mRegisterMapping.insert(x87CW_PM, "x87CW_PM");
        mRegisterPlaces.insert(x87CW_PM, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(x87CW_PM, Register_Relative_Position(x87CW_ZM, x87CW_UM, x87ControlWord, x87CW_PC));

        mRegisterMapping.insert(x87CW_UM, "x87CW_UM");
        mRegisterPlaces.insert(x87CW_UM, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87CW_UM, Register_Relative_Position(x87CW_PM, x87CW_OM, x87CW_IC, x87CW_DM));
        mRegisterMapping.insert(x87CW_OM, "x87CW_OM");
        mRegisterPlaces.insert(x87CW_OM, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87CW_OM, Register_Relative_Position(x87CW_UM, x87CW_PC, x87CW_ZM, x87CW_IM));
        mRegisterMapping.insert(x87CW_PC, "x87CW_PC");
        mRegisterPlaces.insert(x87CW_PC, Register_Position(offset++, 25, 10, 14));
        mRegisterRelativePlaces.insert(x87CW_PC, Register_Relative_Position(x87CW_OM, x87CW_DM, x87CW_PM, x87CW_RC));

        mRegisterMapping.insert(x87CW_DM, "x87CW_DM");
        mRegisterPlaces.insert(x87CW_DM, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(x87CW_DM, Register_Relative_Position(x87CW_PC, x87CW_IM, x87CW_UM, MxCsr));
        mRegisterMapping.insert(x87CW_IM, "x87CW_IM");
        mRegisterPlaces.insert(x87CW_IM, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(x87CW_IM, Register_Relative_Position(x87CW_DM, x87CW_RC, x87CW_OM, MxCsr));
        mRegisterMapping.insert(x87CW_RC, "x87CW_RC");
        mRegisterPlaces.insert(x87CW_RC, Register_Position(offset++, 25, 10, 14));
        mRegisterRelativePlaces.insert(x87CW_RC, Register_Relative_Position(x87CW_IM, MxCsr, x87CW_PC, MxCsr));

        offset++;

        mRegisterMapping.insert(MxCsr, "MxCsr");
        mRegisterPlaces.insert(MxCsr, Register_Position(offset++, 0, 6, sizeof(DWORD) * 2));
        mRegisterRelativePlaces.insert(MxCsr, Register_Relative_Position(x87CW_RC, MxCsr_FZ));

        mRegisterMapping.insert(MxCsr_FZ, "MxCsr_FZ");
        mRegisterPlaces.insert(MxCsr_FZ, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(MxCsr_FZ, Register_Relative_Position(MxCsr, MxCsr_PM, MxCsr, MxCsr_OM));
        mRegisterMapping.insert(MxCsr_PM, "MxCsr_PM");
        mRegisterPlaces.insert(MxCsr_PM, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_PM, Register_Relative_Position(MxCsr_FZ, MxCsr_UM, MxCsr, MxCsr_ZM));
        mRegisterMapping.insert(MxCsr_UM, "MxCsr_UM");
        mRegisterPlaces.insert(MxCsr_UM, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_UM, Register_Relative_Position(MxCsr_PM, MxCsr_OM, MxCsr, MxCsr_IM));

        mRegisterMapping.insert(MxCsr_OM, "MxCsr_OM");
        mRegisterPlaces.insert(MxCsr_OM, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(MxCsr_OM, Register_Relative_Position(MxCsr_UM, MxCsr_ZM, MxCsr_FZ, MxCsr_UE));
        mRegisterMapping.insert(MxCsr_ZM, "MxCsr_ZM");
        mRegisterPlaces.insert(MxCsr_ZM, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_ZM, Register_Relative_Position(MxCsr_OM, MxCsr_IM, MxCsr_PM, MxCsr_PE));
        mRegisterMapping.insert(MxCsr_IM, "MxCsr_IM");
        mRegisterPlaces.insert(MxCsr_IM, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_IM, Register_Relative_Position(MxCsr_ZM, MxCsr_UE, MxCsr_UM, MxCsr_DAZ));

        mRegisterMapping.insert(MxCsr_UE, "MxCsr_UE");
        mRegisterPlaces.insert(MxCsr_UE, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(MxCsr_UE, Register_Relative_Position(MxCsr_IM, MxCsr_PE, MxCsr_OM, MxCsr_OE));
        mRegisterMapping.insert(MxCsr_PE, "MxCsr_PE");
        mRegisterPlaces.insert(MxCsr_PE, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_PE, Register_Relative_Position(MxCsr_UE, MxCsr_DAZ, MxCsr_ZM, MxCsr_ZE));
        mRegisterMapping.insert(MxCsr_DAZ, "MxCsr_DAZ");
        mRegisterPlaces.insert(MxCsr_DAZ, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_DAZ, Register_Relative_Position(MxCsr_PE, MxCsr_OE, MxCsr_IM, MxCsr_DE));

        mRegisterMapping.insert(MxCsr_OE, "MxCsr_OE");
        mRegisterPlaces.insert(MxCsr_OE, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(MxCsr_OE, Register_Relative_Position(MxCsr_DAZ, MxCsr_ZE, MxCsr_UE, MxCsr_IE));
        mRegisterMapping.insert(MxCsr_ZE, "MxCsr_ZE");
        mRegisterPlaces.insert(MxCsr_ZE, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_ZE, Register_Relative_Position(MxCsr_OE, MxCsr_DE, MxCsr_PE, MxCsr_DM));
        mRegisterMapping.insert(MxCsr_DE, "MxCsr_DE");
        mRegisterPlaces.insert(MxCsr_DE, Register_Position(offset++, 25, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_DE, Register_Relative_Position(MxCsr_ZE, MxCsr_IE, MxCsr_DAZ, MxCsr_RC));

        mRegisterMapping.insert(MxCsr_IE, "MxCsr_IE");
        mRegisterPlaces.insert(MxCsr_IE, Register_Position(offset, 0, 9, 1));
        mRegisterRelativePlaces.insert(MxCsr_IE, Register_Relative_Position(MxCsr_DE, MxCsr_DM, MxCsr_OE, XMM0));
        mRegisterMapping.insert(MxCsr_DM, "MxCsr_DM");
        mRegisterPlaces.insert(MxCsr_DM, Register_Position(offset, 12, 10, 1));
        mRegisterRelativePlaces.insert(MxCsr_DM, Register_Relative_Position(MxCsr_IE, MxCsr_RC, MxCsr_ZE, XMM0));
        mRegisterMapping.insert(MxCsr_RC, "MxCsr_RC");
        mRegisterPlaces.insert(MxCsr_RC, Register_Position(offset++, 25, 10, 19));
        mRegisterRelativePlaces.insert(MxCsr_RC, Register_Relative_Position(MxCsr_DM, XMM0, MxCsr_DE, XMM0));

        offset++;

        mRegisterMapping.insert(XMM0, "XMM0");
        mRegisterPlaces.insert(XMM0, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM0, Register_Relative_Position(MxCsr_RC, XMM1));
        mRegisterMapping.insert(XMM1, "XMM1");
        mRegisterPlaces.insert(XMM1, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM1, Register_Relative_Position(XMM0, XMM2));
        mRegisterMapping.insert(XMM2, "XMM2");
        mRegisterPlaces.insert(XMM2, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM2, Register_Relative_Position(XMM1, XMM3));
        mRegisterMapping.insert(XMM3, "XMM3");
        mRegisterPlaces.insert(XMM3, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM3, Register_Relative_Position(XMM2, XMM4));
        mRegisterMapping.insert(XMM4, "XMM4");
        mRegisterPlaces.insert(XMM4, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM4, Register_Relative_Position(XMM3, XMM5));
        mRegisterMapping.insert(XMM5, "XMM5");
        mRegisterPlaces.insert(XMM5, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM5, Register_Relative_Position(XMM4, XMM6));
        mRegisterMapping.insert(XMM6, "XMM6");
        mRegisterPlaces.insert(XMM6, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM6, Register_Relative_Position(XMM5, XMM7));
#ifdef _WIN64
        mRegisterMapping.insert(XMM7, "XMM7");
        mRegisterPlaces.insert(XMM7, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM7, Register_Relative_Position(XMM6, XMM8));
        mRegisterMapping.insert(XMM8, "XMM8");
        mRegisterPlaces.insert(XMM8, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM8, Register_Relative_Position(XMM7, XMM9));
        mRegisterMapping.insert(XMM9, "XMM9");
        mRegisterPlaces.insert(XMM9, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM9, Register_Relative_Position(XMM8, XMM10));
        mRegisterMapping.insert(XMM10, "XMM10");
        mRegisterPlaces.insert(XMM10, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM10, Register_Relative_Position(XMM9, XMM11));
        mRegisterMapping.insert(XMM11, "XMM11");
        mRegisterPlaces.insert(XMM11, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM11, Register_Relative_Position(XMM10, XMM12));
        mRegisterMapping.insert(XMM12, "XMM12");
        mRegisterPlaces.insert(XMM12, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM12, Register_Relative_Position(XMM11, XMM13));
        mRegisterMapping.insert(XMM13, "XMM13");
        mRegisterPlaces.insert(XMM13, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM13, Register_Relative_Position(XMM12, XMM14));
        mRegisterMapping.insert(XMM14, "XMM14");
        mRegisterPlaces.insert(XMM14, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM14, Register_Relative_Position(XMM13, XMM15));
        mRegisterMapping.insert(XMM15, "XMM15");
        mRegisterPlaces.insert(XMM15, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM15, Register_Relative_Position(XMM14, YMM0));
#else
        mRegisterMapping.insert(XMM7, "XMM7");
        mRegisterPlaces.insert(XMM7, Register_Position(offset++, 0, 6, 16 * 2));
        mRegisterRelativePlaces.insert(XMM7, Register_Relative_Position(XMM6, YMM0));
#endif

        offset++;

#ifdef _WIN64
        mRegisterMapping.insert(YMM0, "YMM0");
        mRegisterPlaces.insert(YMM0, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM0, Register_Relative_Position(XMM15, YMM1));
#else
        mRegisterMapping.insert(YMM0, "YMM0");
        mRegisterPlaces.insert(YMM0, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM0, Register_Relative_Position(XMM7, YMM1));
#endif
        mRegisterMapping.insert(YMM1, "YMM1");
        mRegisterPlaces.insert(YMM1, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM1, Register_Relative_Position(YMM0, YMM2));
        mRegisterMapping.insert(YMM2, "YMM2");
        mRegisterPlaces.insert(YMM2, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM2, Register_Relative_Position(YMM1, YMM3));
        mRegisterMapping.insert(YMM3, "YMM3");
        mRegisterPlaces.insert(YMM3, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM3, Register_Relative_Position(YMM2, YMM4));
        mRegisterMapping.insert(YMM4, "YMM4");
        mRegisterPlaces.insert(YMM4, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM4, Register_Relative_Position(YMM3, YMM5));
        mRegisterMapping.insert(YMM5, "YMM5");
        mRegisterPlaces.insert(YMM5, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM5, Register_Relative_Position(YMM4, YMM6));
        mRegisterMapping.insert(YMM6, "YMM6");
        mRegisterPlaces.insert(YMM6, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM6, Register_Relative_Position(YMM5, YMM7));
#ifdef _WIN64
        mRegisterMapping.insert(YMM7, "YMM7");
        mRegisterPlaces.insert(YMM7, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM7, Register_Relative_Position(YMM6, YMM8));
        mRegisterMapping.insert(YMM8, "YMM8");
        mRegisterPlaces.insert(YMM8, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM8, Register_Relative_Position(YMM7, YMM9));
        mRegisterMapping.insert(YMM9, "YMM9");
        mRegisterPlaces.insert(YMM9, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM9, Register_Relative_Position(YMM8, YMM10));
        mRegisterMapping.insert(YMM10, "YMM10");
        mRegisterPlaces.insert(YMM10, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM10, Register_Relative_Position(YMM9, YMM11));
        mRegisterMapping.insert(YMM11, "YMM11");
        mRegisterPlaces.insert(YMM11, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM11, Register_Relative_Position(YMM10, YMM12));
        mRegisterMapping.insert(YMM12, "YMM12");
        mRegisterPlaces.insert(YMM12, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM12, Register_Relative_Position(YMM11, YMM13));
        mRegisterMapping.insert(YMM13, "YMM13");
        mRegisterPlaces.insert(YMM13, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM13, Register_Relative_Position(YMM12, YMM14));
        mRegisterMapping.insert(YMM14, "YMM14");
        mRegisterPlaces.insert(YMM14, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM14, Register_Relative_Position(YMM13, YMM15));
        mRegisterMapping.insert(YMM15, "YMM15");
        mRegisterPlaces.insert(YMM15, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM15, Register_Relative_Position(YMM14, DR0));
#else
        mRegisterMapping.insert(YMM7, "YMM7");
        mRegisterPlaces.insert(YMM7, Register_Position(offset++, 0, 6, 32 * 2));
        mRegisterRelativePlaces.insert(YMM7, Register_Relative_Position(YMM6, DR0));
#endif
#endif
  }
#if 0
    else
    {
        mRegisterRelativePlaces.insert(CS, Register_Relative_Position(DS, SS, ES, DR0));
        mRegisterRelativePlaces.insert(SS, Register_Relative_Position(CS, DR0, DS, DR0));
    }

    offset++;

    if(mShowFpu)
    {
#ifdef _WIN64
        mRegisterRelativePlaces.insert(DR0, Register_Relative_Position(YMM15, DR1));
#else
        mRegisterRelativePlaces.insert(DR0, Register_Relative_Position(YMM7, DR1));
#endif
    }
    else
    {
        mRegisterRelativePlaces.insert(DR0, Register_Relative_Position(SS, DR1));
    }

    mRegisterMapping.insert(DR0, "DR0");
    mRegisterPlaces.insert(DR0, Register_Position(offset++, 0, 4, sizeof(duint) * 2));
    mRegisterMapping.insert(DR1, "DR1");
    mRegisterPlaces.insert(DR1, Register_Position(offset++, 0, 4, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(DR1, Register_Relative_Position(DR0, DR2));
    mRegisterMapping.insert(DR2, "DR2");
    mRegisterPlaces.insert(DR2, Register_Position(offset++, 0, 4, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(DR2, Register_Relative_Position(DR1, DR3));
    mRegisterMapping.insert(DR3, "DR3");
    mRegisterPlaces.insert(DR3, Register_Position(offset++, 0, 4, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(DR3, Register_Relative_Position(DR2, DR6));
    mRegisterMapping.insert(DR6, "DR6");
    mRegisterPlaces.insert(DR6, Register_Position(offset++, 0, 4, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(DR6, Register_Relative_Position(DR3, DR7));
    mRegisterMapping.insert(DR7, "DR7");
    mRegisterPlaces.insert(DR7, Register_Position(offset++, 0, 4, sizeof(duint) * 2));
    mRegisterRelativePlaces.insert(DR7, Register_Relative_Position(DR6, UNKNOWN));
#endif
  mRowsNeeded = offset + 1;
}

static QAction* setupAction(const QIcon& icon, const QString& text,
                            RegistersViewA64* this_object) {
  QAction* action = new QAction(icon, text, this_object);
  action->setShortcutContext(Qt::WidgetShortcut);
  this_object->addAction(action);
  return action;
}

static QAction* setupAction(const QString& text, RegistersViewA64* this_object) {
  QAction* action = new QAction(text, this_object);
  action->setShortcutContext(Qt::WidgetShortcut);
  this_object->addAction(action);
  return action;
}

RegistersViewA64::RegistersViewA64(QWidget* parent)
    : QScrollArea(parent), mVScrollOffset(0) {
  setWindowTitle("Registers");
  mChangeViewButton = NULL;
  mFpuMode = 2;
  isActive = false;

  // general purposes register (we allow the user to modify the value)
#if 0
    mGPR.insert(CAX);
    mCANSTOREADDRESS.insert(CAX);
    mUINTDISPLAY.insert(CAX);
    mLABELDISPLAY.insert(CAX);
    mMODIFYDISPLAY.insert(CAX);
    mUNDODISPLAY.insert(CAX);
    mINCREMENTDECREMET.insert(CAX);
    mSETONEZEROTOGGLE.insert(CAX);

    mSETONEZEROTOGGLE.insert(CBX);
    mINCREMENTDECREMET.insert(CBX);
    mGPR.insert(CBX);
    mUINTDISPLAY.insert(CBX);
    mLABELDISPLAY.insert(CBX);
    mMODIFYDISPLAY.insert(CBX);
    mUNDODISPLAY.insert(CBX);
    mCANSTOREADDRESS.insert(CBX);

    mSETONEZEROTOGGLE.insert(CCX);
    mINCREMENTDECREMET.insert(CCX);
    mGPR.insert(CCX);
    mUINTDISPLAY.insert(CCX);
    mLABELDISPLAY.insert(CCX);
    mMODIFYDISPLAY.insert(CCX);
    mUNDODISPLAY.insert(CCX);
    mCANSTOREADDRESS.insert(CCX);

    mSETONEZEROTOGGLE.insert(CDX);
    mINCREMENTDECREMET.insert(CDX);
    mGPR.insert(CDX);
    mUINTDISPLAY.insert(CDX);
    mLABELDISPLAY.insert(CDX);
    mMODIFYDISPLAY.insert(CDX);
    mUNDODISPLAY.insert(CDX);
    mCANSTOREADDRESS.insert(CDX);

    mSETONEZEROTOGGLE.insert(CBP);
    mINCREMENTDECREMET.insert(CBP);
    mCANSTOREADDRESS.insert(CBP);
    mGPR.insert(CBP);
    mUINTDISPLAY.insert(CBP);
    mLABELDISPLAY.insert(CBP);
    mMODIFYDISPLAY.insert(CBP);
    mUNDODISPLAY.insert(CBP);

    mSETONEZEROTOGGLE.insert(CSP);
    mINCREMENTDECREMET.insert(CSP);
    mCANSTOREADDRESS.insert(CSP);
    mGPR.insert(CSP);
    mUINTDISPLAY.insert(CSP);
    mLABELDISPLAY.insert(CSP);
    mMODIFYDISPLAY.insert(CSP);
    mUNDODISPLAY.insert(CSP);

    mSETONEZEROTOGGLE.insert(CSI);
    mINCREMENTDECREMET.insert(CSI);
    mCANSTOREADDRESS.insert(CSI);
    mGPR.insert(CSI);
    mUINTDISPLAY.insert(CSI);
    mLABELDISPLAY.insert(CSI);
    mMODIFYDISPLAY.insert(CSI);
    mUNDODISPLAY.insert(CSI);

    mSETONEZEROTOGGLE.insert(CDI);
    mINCREMENTDECREMET.insert(CDI);
    mCANSTOREADDRESS.insert(CDI);
    mGPR.insert(CDI);
    mUINTDISPLAY.insert(CDI);
    mLABELDISPLAY.insert(CDI);
    mMODIFYDISPLAY.insert(CDI);
    mUNDODISPLAY.insert(CDI);
#ifdef _WIN64
    for(REGISTER_NAME i = R8; i <= R15; i = (REGISTER_NAME)(i + 1))
    {
        mSETONEZEROTOGGLE.insert(i);
        mINCREMENTDECREMET.insert(i);
        mCANSTOREADDRESS.insert(i);
        mGPR.insert(i);
        mLABELDISPLAY.insert(i);
        mUINTDISPLAY.insert(i);
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
    }
#endif  //_WIN64
#else
  for (int i = 0; i < PC; i++) {
    mSETONEZEROTOGGLE.insert(i);
    mINCREMENTDECREMET.insert(i);
    mCANSTOREADDRESS.insert(i);
    mGPR.insert(i);
    mLABELDISPLAY.insert(i);
    mUINTDISPLAY.insert(i);
    mMODIFYDISPLAY.insert(i);
    mUNDODISPLAY.insert(i);
  }
#endif

#if 0
    mSETONEZEROTOGGLE.insert(EFLAGS);
    mGPR.insert(EFLAGS);
    mMODIFYDISPLAY.insert(EFLAGS);
    mUNDODISPLAY.insert(EFLAGS);
    mUINTDISPLAY.insert(EFLAGS);
#else
  mSETONEZEROTOGGLE.insert(FLAGS);
  mGPR.insert(FLAGS);
  mMODIFYDISPLAY.insert(FLAGS);
  mUNDODISPLAY.insert(FLAGS);
  mUINTDISPLAY.insert(FLAGS);
#endif

  // flags (we allow the user to toggle them)
#if 0
    mFlags.insert(CF);
    mBOOLDISPLAY.insert(CF);
    mSETONEZEROTOGGLE.insert(CF);

    mSETONEZEROTOGGLE.insert(PF);
    mFlags.insert(PF);
    mBOOLDISPLAY.insert(PF);

    mSETONEZEROTOGGLE.insert(AF);
    mFlags.insert(AF);
    mBOOLDISPLAY.insert(AF);

    mSETONEZEROTOGGLE.insert(ZF);
    mFlags.insert(ZF);
    mBOOLDISPLAY.insert(ZF);

    mSETONEZEROTOGGLE.insert(SF);
    mFlags.insert(SF);
    mBOOLDISPLAY.insert(SF);

    mSETONEZEROTOGGLE.insert(TF);
    mFlags.insert(TF);
    mBOOLDISPLAY.insert(TF);

    mFlags.insert(IF);
    mBOOLDISPLAY.insert(IF);

    mSETONEZEROTOGGLE.insert(DF);
    mFlags.insert(DF);
    mBOOLDISPLAY.insert(DF);

    mSETONEZEROTOGGLE.insert(OF);
    mFlags.insert(OF);
    mBOOLDISPLAY.insert(OF);
#else
  for (int i = N; i <= V; i++) {
    mSETONEZEROTOGGLE.insert(i);
    mFlags.insert(i);
    mBOOLDISPLAY.insert(i);
  }
#endif
  // FPU: XMM, x87 and MMX registers
#if 0
    mSETONEZEROTOGGLE.insert(MxCsr);
    mDWORDDISPLAY.insert(MxCsr);
    mMODIFYDISPLAY.insert(MxCsr);
    mUNDODISPLAY.insert(MxCsr);
    mFPU.insert(MxCsr);

    for(REGISTER_NAME i = x87r0; i <= x87r7; i = (REGISTER_NAME)(i + 1))
    {
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
        mFPUx87.insert(i);
        mFPUx87_80BITSDISPLAY.insert(i);
        mFPU.insert(i);
        mSETONEZEROTOGGLE.insert(i);
    }

    for(REGISTER_NAME i = x87st0; i <= x87st7; i = (REGISTER_NAME)(i + 1))
    {
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
        mFPUx87.insert(i);
        mFPUx87_80BITSDISPLAY.insert(i);
        mFPU.insert(i);
        mSETONEZEROTOGGLE.insert(i);
    }

    mSETONEZEROTOGGLE.insert(x87TagWord);
    mFPUx87.insert(x87TagWord);
    mMODIFYDISPLAY.insert(x87TagWord);
    mUNDODISPLAY.insert(x87TagWord);
    mUSHORTDISPLAY.insert(x87TagWord);
    mFPU.insert(x87TagWord);

    mSETONEZEROTOGGLE.insert(x87StatusWord);
    mUSHORTDISPLAY.insert(x87StatusWord);
    mMODIFYDISPLAY.insert(x87StatusWord);
    mUNDODISPLAY.insert(x87StatusWord);
    mFPUx87.insert(x87StatusWord);
    mFPU.insert(x87StatusWord);

    mSETONEZEROTOGGLE.insert(x87ControlWord);
    mFPUx87.insert(x87ControlWord);
    mMODIFYDISPLAY.insert(x87ControlWord);
    mUNDODISPLAY.insert(x87ControlWord);
    mUSHORTDISPLAY.insert(x87ControlWord);
    mFPU.insert(x87ControlWord);

    mSETONEZEROTOGGLE.insert(x87SW_B);
    mFPUx87.insert(x87SW_B);
    mBOOLDISPLAY.insert(x87SW_B);
    mFPU.insert(x87SW_B);

    mSETONEZEROTOGGLE.insert(x87SW_C3);
    mFPUx87.insert(x87SW_C3);
    mBOOLDISPLAY.insert(x87SW_C3);
    mFPU.insert(x87SW_C3);

    mFPUx87.insert(x87SW_TOP);
    mFIELDVALUE.insert(x87SW_TOP);
    mFPU.insert(x87SW_TOP);
    mMODIFYDISPLAY.insert(x87SW_TOP);
    mUNDODISPLAY.insert(x87SW_TOP);

    mFPUx87.insert(x87SW_C2);
    mBOOLDISPLAY.insert(x87SW_C2);
    mSETONEZEROTOGGLE.insert(x87SW_C2);
    mFPU.insert(x87SW_C2);

    mSETONEZEROTOGGLE.insert(x87SW_C1);
    mFPUx87.insert(x87SW_C1);
    mBOOLDISPLAY.insert(x87SW_C1);
    mFPU.insert(x87SW_C1);

    mSETONEZEROTOGGLE.insert(x87SW_C0);
    mFPUx87.insert(x87SW_C0);
    mBOOLDISPLAY.insert(x87SW_C0);
    mFPU.insert(x87SW_C0);

    mSETONEZEROTOGGLE.insert(x87SW_ES);
    mFPUx87.insert(x87SW_ES);
    mBOOLDISPLAY.insert(x87SW_ES);
    mFPU.insert(x87SW_ES);

    mSETONEZEROTOGGLE.insert(x87SW_SF);
    mFPUx87.insert(x87SW_SF);
    mBOOLDISPLAY.insert(x87SW_SF);
    mFPU.insert(x87SW_SF);

    mSETONEZEROTOGGLE.insert(x87SW_P);
    mFPUx87.insert(x87SW_P);
    mBOOLDISPLAY.insert(x87SW_P);
    mFPU.insert(x87SW_P);

    mSETONEZEROTOGGLE.insert(x87SW_U);
    mFPUx87.insert(x87SW_U);
    mBOOLDISPLAY.insert(x87SW_U);
    mFPU.insert(x87SW_U);

    mSETONEZEROTOGGLE.insert(x87SW_O);
    mFPUx87.insert(x87SW_O);
    mBOOLDISPLAY.insert(x87SW_O);
    mFPU.insert(x87SW_O);

    mSETONEZEROTOGGLE.insert(x87SW_Z);
    mFPUx87.insert(x87SW_Z);
    mBOOLDISPLAY.insert(x87SW_Z);
    mFPU.insert(x87SW_Z);

    mSETONEZEROTOGGLE.insert(x87SW_D);
    mFPUx87.insert(x87SW_D);
    mBOOLDISPLAY.insert(x87SW_D);
    mFPU.insert(x87SW_D);

    mSETONEZEROTOGGLE.insert(x87SW_I);
    mFPUx87.insert(x87SW_I);
    mBOOLDISPLAY.insert(x87SW_I);
    mFPU.insert(x87SW_I);

    mSETONEZEROTOGGLE.insert(x87CW_IC);
    mFPUx87.insert(x87CW_IC);
    mBOOLDISPLAY.insert(x87CW_IC);
    mFPU.insert(x87CW_IC);

    mFPUx87.insert(x87CW_RC);
    mFIELDVALUE.insert(x87CW_RC);
    mFPU.insert(x87CW_RC);
    mMODIFYDISPLAY.insert(x87CW_RC);
    mUNDODISPLAY.insert(x87CW_RC);

    for(REGISTER_NAME i = x87TW_0; i <= x87TW_7; i = (REGISTER_NAME)(i + 1))
    {
        mFPUx87.insert(i);
        mFIELDVALUE.insert(i);
        mTAGWORD.insert(i);
        mFPU.insert(i);
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
    }

    mFPUx87.insert(x87CW_PC);
    mFIELDVALUE.insert(x87CW_PC);
    mFPU.insert(x87CW_PC);
    mMODIFYDISPLAY.insert(x87CW_PC);
    mUNDODISPLAY.insert(x87CW_PC);

    mSETONEZEROTOGGLE.insert(x87CW_PM);
    mFPUx87.insert(x87CW_PM);
    mBOOLDISPLAY.insert(x87CW_PM);
    mFPU.insert(x87CW_PM);

    mSETONEZEROTOGGLE.insert(x87CW_UM);
    mFPUx87.insert(x87CW_UM);
    mBOOLDISPLAY.insert(x87CW_UM);
    mFPU.insert(x87CW_UM);

    mSETONEZEROTOGGLE.insert(x87CW_OM);
    mFPUx87.insert(x87CW_OM);
    mBOOLDISPLAY.insert(x87CW_OM);
    mFPU.insert(x87CW_OM);

    mSETONEZEROTOGGLE.insert(x87CW_ZM);
    mFPUx87.insert(x87CW_ZM);
    mBOOLDISPLAY.insert(x87CW_ZM);
    mFPU.insert(x87CW_ZM);

    mSETONEZEROTOGGLE.insert(x87CW_DM);
    mFPUx87.insert(x87CW_DM);
    mBOOLDISPLAY.insert(x87CW_DM);
    mFPU.insert(x87CW_DM);

    mSETONEZEROTOGGLE.insert(x87CW_IM);
    mFPUx87.insert(x87CW_IM);
    mBOOLDISPLAY.insert(x87CW_IM);
    mFPU.insert(x87CW_IM);

    mSETONEZEROTOGGLE.insert(MxCsr_FZ);
    mBOOLDISPLAY.insert(MxCsr_FZ);
    mFPU.insert(MxCsr_FZ);

    mSETONEZEROTOGGLE.insert(MxCsr_PM);
    mBOOLDISPLAY.insert(MxCsr_PM);
    mFPU.insert(MxCsr_PM);

    mSETONEZEROTOGGLE.insert(MxCsr_UM);
    mBOOLDISPLAY.insert(MxCsr_UM);
    mFPU.insert(MxCsr_UM);

    mSETONEZEROTOGGLE.insert(MxCsr_OM);
    mBOOLDISPLAY.insert(MxCsr_OM);
    mFPU.insert(MxCsr_OM);

    mSETONEZEROTOGGLE.insert(MxCsr_ZM);
    mBOOLDISPLAY.insert(MxCsr_ZM);
    mFPU.insert(MxCsr_ZM);

    mSETONEZEROTOGGLE.insert(MxCsr_IM);
    mBOOLDISPLAY.insert(MxCsr_IM);
    mFPU.insert(MxCsr_IM);

    mSETONEZEROTOGGLE.insert(MxCsr_DM);
    mBOOLDISPLAY.insert(MxCsr_DM);
    mFPU.insert(MxCsr_DM);

    mSETONEZEROTOGGLE.insert(MxCsr_DAZ);
    mBOOLDISPLAY.insert(MxCsr_DAZ);
    mFPU.insert(MxCsr_DAZ);

    mSETONEZEROTOGGLE.insert(MxCsr_PE);
    mBOOLDISPLAY.insert(MxCsr_PE);
    mFPU.insert(MxCsr_PE);

    mSETONEZEROTOGGLE.insert(MxCsr_UE);
    mBOOLDISPLAY.insert(MxCsr_UE);
    mFPU.insert(MxCsr_UE);

    mSETONEZEROTOGGLE.insert(MxCsr_OE);
    mBOOLDISPLAY.insert(MxCsr_OE);
    mFPU.insert(MxCsr_OE);

    mSETONEZEROTOGGLE.insert(MxCsr_ZE);
    mBOOLDISPLAY.insert(MxCsr_ZE);
    mFPU.insert(MxCsr_ZE);

    mSETONEZEROTOGGLE.insert(MxCsr_DE);
    mBOOLDISPLAY.insert(MxCsr_DE);
    mFPU.insert(MxCsr_DE);

    mSETONEZEROTOGGLE.insert(MxCsr_IE);
    mBOOLDISPLAY.insert(MxCsr_IE);
    mFPU.insert(MxCsr_IE);

    mFIELDVALUE.insert(MxCsr_RC);
    mFPU.insert(MxCsr_RC);
    mMODIFYDISPLAY.insert(MxCsr_RC);
    mUNDODISPLAY.insert(MxCsr_RC);

    for(REGISTER_NAME i = MM0; i <= MM7; i = (REGISTER_NAME)(i + 1))
    {
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
        mFPUMMX.insert(i);
        mFPU.insert(i);
    }

    for(REGISTER_NAME i = XMM0; i <= ArchValue(XMM7, XMM15); i = (REGISTER_NAME)(i + 1))
    {
        mFPUXMM.insert(i);
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
        mFPU.insert(i);
    }

    for(REGISTER_NAME i = YMM0; i <= ArchValue(YMM7, YMM15); i = (REGISTER_NAME)(i + 1))
    {
        mFPUYMM.insert(i);
        mMODIFYDISPLAY.insert(i);
        mUNDODISPLAY.insert(i);
        mFPU.insert(i);
    }

    //registers that should not be changed
    mNoChange.insert(LastError);
    mNoChange.insert(LastStatus);

    mNoChange.insert(GS);
    mUSHORTDISPLAY.insert(GS);
    mSEGMENTREGISTER.insert(GS);

    mNoChange.insert(FS);
    mUSHORTDISPLAY.insert(FS);
    mSEGMENTREGISTER.insert(FS);

    mNoChange.insert(ES);
    mUSHORTDISPLAY.insert(ES);
    mSEGMENTREGISTER.insert(ES);

    mNoChange.insert(DS);
    mUSHORTDISPLAY.insert(DS);
    mSEGMENTREGISTER.insert(DS);

    mNoChange.insert(CS);
    mUSHORTDISPLAY.insert(CS);
    mSEGMENTREGISTER.insert(CS);

    mNoChange.insert(SS);
    mUSHORTDISPLAY.insert(SS);
    mSEGMENTREGISTER.insert(SS);

    mNoChange.insert(DR0);
    mUINTDISPLAY.insert(DR0);
    mLABELDISPLAY.insert(DR0);
    mONLYMODULEANDLABELDISPLAY.insert(DR0);
    mCANSTOREADDRESS.insert(DR0);

    mNoChange.insert(DR1);
    mONLYMODULEANDLABELDISPLAY.insert(DR1);
    mUINTDISPLAY.insert(DR1);
    mCANSTOREADDRESS.insert(DR1);

    mLABELDISPLAY.insert(DR2);
    mONLYMODULEANDLABELDISPLAY.insert(DR2);
    mNoChange.insert(DR2);
    mUINTDISPLAY.insert(DR2);
    mCANSTOREADDRESS.insert(DR2);

    mNoChange.insert(DR3);
    mONLYMODULEANDLABELDISPLAY.insert(DR3);
    mLABELDISPLAY.insert(DR3);
    mUINTDISPLAY.insert(DR3);
    mCANSTOREADDRESS.insert(DR3);

    mNoChange.insert(DR6);
    mUINTDISPLAY.insert(DR6);

    mNoChange.insert(DR7);
    mUINTDISPLAY.insert(DR7);
#else
  for (int i = 0; i < 32; i++) {
    mFPUXMM.insert(Q0 + i);
    mMODIFYDISPLAY.insert(Q0 + i);
    mUNDODISPLAY.insert(Q0 + i);
    mFPU.insert(Q0 + i);
  }
#endif

#if 0
    mNoChange.insert(CIP);
    mUINTDISPLAY.insert(CIP);
    mLABELDISPLAY.insert(CIP);
    mONLYMODULEANDLABELDISPLAY.insert(CIP);
    mCANSTOREADDRESS.insert(CIP);
    mMODIFYDISPLAY.insert(CIP);
    mUNDODISPLAY.insert(CIP);
#else
  mNoChange.insert(PC);
  mUINTDISPLAY.insert(PC);
  mLABELDISPLAY.insert(PC);
  mONLYMODULEANDLABELDISPLAY.insert(PC);
  mCANSTOREADDRESS.insert(PC);
  mMODIFYDISPLAY.insert(PC);
  mUNDODISPLAY.insert(PC);
#endif

  fontsUpdatedSlot();
  connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
  // self communication for repainting (maybe some other widgets needs this
  // information, too)
  connect(this, SIGNAL(refresh()), this, SLOT(reload()));

  InitMappings();

  memset(&wRegDumpStruct, 0, sizeof(REGDUMPA64));
  memset(&wCipRegDumpStruct, 0, sizeof(REGDUMPA64));
  mCip = 0;
  mRegisterUpdates.clear();

  mButtonHeight = 0;
  yTopSpacing = 4;  // set top spacing (in pixels)

  this->setMouseTracking(true);
}

void RegistersViewA64::refreshShortcutsSlot() {}

/**
 * @brief RegistersViewA64::~RegistersViewA64 The destructor.
 */
RegistersViewA64::~RegistersViewA64() {}

void RegistersViewA64::fontsUpdatedSlot() {
  if (!isEnabled()) return;

  auto font = ConfigFont("Registers");
  setFont(font);
  if (mChangeViewButton) mChangeViewButton->setFont(font);
  // update metrics information
  int wRowsHeight = QFontMetrics(this->font()).height();
  wRowsHeight = (wRowsHeight * 105) / 100;
  wRowsHeight = (wRowsHeight % 2) == 0 ? wRowsHeight : wRowsHeight + 1;
  mRowHeight = wRowsHeight;
  mCharWidth = QFontMetrics(this->font()).averageCharWidth();

  // reload layout because the layout is dependent on the font.
  InitMappings();
  // adjust the height of the area.
  setFixedHeight(getEstimateHeight());
  reload();
}

void RegistersViewA64::displayCustomContextMenuSlot(QPoint pos) {}

void RegistersViewA64::ShowFPU(bool set_showfpu) {
  mShowFpu = set_showfpu;
  InitMappings();
  setFixedHeight(getEstimateHeight());
  reload();
}

/**
 * @brief retrieves the register id from given corrdinates of the viewport
 * @param line
 * @param offset (x-coord)
 * @param resulting register-id
 * @return true if register found
 */
bool RegistersViewA64::identifyRegister(const int line, const int offset,
                                     REGISTER_NAME* clickedReg) {
  // we start by an unknown register id
  if (clickedReg) *clickedReg = UNKNOWN;
  bool found_flag = false;
  QMap<REGISTER_NAME, Register_Position>::const_iterator it =
      mRegisterPlaces.begin();
  // iterate all registers that being displayed
  while (it != mRegisterPlaces.end()) {
    if ((it.value().line == (line - mVScrollOffset)) /* same line ? */
        && ((1 + it.value().start) <= offset)        /* between start ... ? */
        && (offset <= (1 + it.value().start + it.value().labelwidth +
                       it.value().valuesize)) /* ... and end ? */
    ) {
      // we found a matching register in the viewport
      if (clickedReg) *clickedReg = (REGISTER_NAME)it.key();
      found_flag = true;
      break;
    }
    ++it;
  }
  return found_flag;
}

/**
 * @brief RegistersViewA64::helpRegister Get the help information of a register.
 * The help information is from Intel's manual.
 * @param reg The register name
 * @return The help information, possibly translated to the native language, or
 * empty if the help information is not available yet.
 */
QString RegistersViewA64::helpRegister(REGISTER_NAME reg) {
  switch (reg) {
    // We don't display help messages for general purpose registers as they are
    // very well-known.
    case C:
      return tr(
          "CF (bit 0) : Carry flag - Set if an arithmetic operation generates "
          "a carry or a borrow out of the mostsignificant bit of the result; "
          "cleared otherwise.\n"
          "This flag indicates an overflow condition for unsigned-integer "
          "arithmetic. It is also used in multiple-precision arithmetic.");
#if 0
    case PF:
        return tr("PF (bit 2) : Parity flag - Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise.");
    case AF:
        return tr("AF (bit 4) : Auxiliary Carry flag - Set if an arithmetic operation generates a carry or a borrow out of bit\n"
                  "3 of the result; cleared otherwise. This flag is used in binary-coded decimal (BCD) arithmetic.");
#endif
    case Z:
      return tr(
          "ZF (bit 6) : Zero flag - Set if the result is zero; cleared "
          "otherwise.");
    case N:
      return tr(
          "NF (bit 7) : Sign flag - Set equal to the most-significant bit of "
          "the result, which is the sign bit of a signed\n"
          "integer. (0 indicates a positive value and 1 indicates a negative "
          "value.)");
    case V:
      return tr(
          "VF (bit 11) : Overflow flag - Set if the integer result is too "
          "large a positive number or too small a negative\n"
          "number (excluding the sign-bit) to fit in the destination operand; "
          "cleared otherwise. This flag indicates an overflow\n"
          "condition for signed-integer (two’s complement) arithmetic.");
#if 0
    case DF:
        return tr("DF (bit 10) : The direction flag controls string instructions (MOVS, CMPS, SCAS, LODS, and STOS). Setting the DF flag causes the string instructions\n"
                  "to auto-decrement (to process strings from high addresses to low addresses). Clearing the DF flag causes the string instructions to auto-increment\n"
                  "(process strings from low addresses to high addresses).");
    case TF:
        return tr("TF (bit 8) : Trap flag - Set to enable single-step mode for debugging; clear to disable single-step mode.");
    case IF:
        return tr("IF (bit 9) : Interrupt enable flag - Controls the response of the processor to maskable interrupt requests. Set to respond to maskable interrupts; cleared to inhibit maskable interrupts.");
    case x87ControlWord:
        return tr("The 16-bit x87 FPU control word controls the precision of the x87 FPU and rounding method used. It also contains the x87 FPU floating-point exception mask bits.");
    case x87StatusWord:
        return tr("The 16-bit x87 FPU status register indicates the current state of the x87 FPU.");
    case x87TagWord:
        return tr("The 16-bit tag word indicates the contents of each the 8 registers in the x87 FPU data-register stack (one 2-bit tag per register).");

    case x87CW_PC:
        return tr("The precision-control (PC) field (bits 8 and 9 of the x87 FPU control word) determines the precision (64, 53, or 24 bits) of floating-point calculations made by the x87 FPU");
    case x87CW_RC:
        return tr("The rounding-control (RC) field of the x87 FPU control register (bits 10 and 11) controls how the results of x87 FPU floating-point instructions are rounded.");
    case x87CW_IC:
        return tr("The infinity control flag (bit 12 of the x87 FPU control word) is provided for compatibility with the Intel 287 Math Coprocessor;\n"
                  "it is not meaningful for later version x87 FPU coprocessors or IA-32 processors.");
    case x87CW_IM:
        return tr("The invalid operation exception mask (bit 0). When the mask bit is set, its corresponding exception is blocked from being generated.");
    case x87CW_DM:
        return tr("The denormal-operand exception mask (bit 2). When the mask bit is set, its corresponding exception is blocked from being generated.");
    case x87CW_ZM:
        return tr("The floating-point divide-by-zero exception mask (bit 3). When the mask bit is set, its corresponding exception is blocked from being generated.");
    case x87CW_OM:
        return tr("The floating-point numeric overflow exception mask (bit 4). When the mask bit is set, its corresponding exception is blocked from being generated.");
    case x87CW_UM:
        return tr("The potential floating-point numeric underflow condition mask (bit 5). When the mask bit is set, its corresponding exception is blocked from being generated.");
    case x87CW_PM:
        return tr("The inexact-result/precision exception mask (bit 6). When the mask bit is set, its corresponding exception is blocked from being generated.");

    case x87SW_B:
        return tr("The busy flag (bit 15) indicates if the FPU is busy (B=1) while executing an instruction, or is idle (B=0).\n"
                  "The B-bit (bit 15) is included for 8087 compatibility only. It reflects the contents of the ES flag.");
    case x87SW_C0:
        return tr("The C%1 condition code flag (bit %2) is used to indicate the results of floating-point comparison and arithmetic operations.").arg(0).arg(8);
    case x87SW_C1:
        return tr("The C%1 condition code flag (bit %2) is used to indicate the results of floating-point comparison and arithmetic operations.").arg(1).arg(9);
    case x87SW_C2:
        return tr("The C%1 condition code flag (bit %2) is used to indicate the results of floating-point comparison and arithmetic operations.").arg(2).arg(10);
    case x87SW_C3:
        return tr("The C%1 condition code flag (bit %2) is used to indicate the results of floating-point comparison and arithmetic operations.").arg(3).arg(14);
    case x87SW_ES:
        return tr("The error/exception summary status flag (bit 7) is set when any of the unmasked exception flags are set.");
    case x87SW_SF:
        return tr("The stack fault flag (bit 6 of the x87 FPU status word) indicates that stack overflow or stack underflow has occurred with data\nin the x87 FPU data register stack.");
    case x87SW_TOP:
        return tr("A pointer to the x87 FPU data register that is currently at the top of the x87 FPU register stack is contained in bits 11 through 13\n"
                  "of the x87 FPU status word. This pointer, which is commonly referred to as TOP (for top-of-stack), is a binary value from 0 to 7.");
    case x87SW_I:
        return tr("The processor reports an invalid operation exception (bit 0) in response to one or more invalid arithmetic operands.");
    case x87SW_D:
        return tr("The processor reports the denormal-operand exception (bit 2) if an arithmetic instruction attempts to operate on a denormal operand.");
    case x87SW_Z:
        return tr("The processor reports the floating-point divide-by-zero exception (bit 3) whenever an instruction attempts to divide a finite non-zero operand by 0.");
    case x87SW_O:
        return tr("The processor reports a floating-point numeric overflow exception (bit 4) whenever the rounded result of an instruction exceeds the largest allowable finite value that will fit into the destination operand.");
    case x87SW_U:
        return tr("The processor detects a potential floating-point numeric underflow condition (bit 5) whenever the result of rounding with unbounded exponent is non-zero and tiny.");
    case x87SW_P:
        return tr("The inexact-result/precision exception (bit 6) occurs if the result of an operation is not exactly representable in the destination format.");

    case MxCsr:
        return tr("The 32-bit MXCSR register contains control and status information for SIMD floating-point operations.");
    case MxCsr_IE:
        return tr("Bit 0 (IE) : Invalid Operation Flag; indicate whether a SIMD floating-point exception has been detected.");
    case MxCsr_DE:
        return tr("Bit 1 (DE) : Denormal Flag; indicate whether a SIMD floating-point exception has been detected.");
    case MxCsr_ZE:
        return tr("Bit 2 (ZE) : Divide-by-Zero Flag; indicate whether a SIMD floating-point exception has been detected.");
    case MxCsr_OE:
        return tr("Bit 3 (OE) : Overflow Flag; indicate whether a SIMD floating-point exception has been detected.");
    case MxCsr_UE:
        return tr("Bit 4 (UE) : Underflow Flag; indicate whether a SIMD floating-point exception has been detected.");
    case MxCsr_PE:
        return tr("Bit 5 (PE) : Precision Flag; indicate whether a SIMD floating-point exception has been detected.");
    case MxCsr_IM:
        return tr("Bit 7 (IM) : Invalid Operation Mask. When the mask bit is set, its corresponding exception is blocked from being generated.");
    case MxCsr_DM:
        return tr("Bit 8 (DM) : Denormal Mask. When the mask bit is set, its corresponding exception is blocked from being generated.");
    case MxCsr_ZM:
        return tr("Bit 9 (ZM) : Divide-by-Zero Mask. When the mask bit is set, its corresponding exception is blocked from being generated.");
    case MxCsr_OM:
        return tr("Bit 10 (OM) : Overflow Mask. When the mask bit is set, its corresponding exception is blocked from being generated.");
    case MxCsr_UM:
        return tr("Bit 11 (UM) : Underflow Mask. When the mask bit is set, its corresponding exception is blocked from being generated.");
    case MxCsr_PM:
        return tr("Bit 12 (PM) : Precision Mask. When the mask bit is set, its corresponding exception is blocked from being generated.");
    case MxCsr_FZ:
        return tr("Bit 15 (FZ) of the MXCSR register enables the flush-to-zero mode, which controls the masked response to a SIMD floating-point underflow condition.");
    case MxCsr_DAZ:
        return tr("Bit 6 (DAZ) of the MXCSR register enables the denormals-are-zeros mode, which controls the processor’s response to a SIMD floating-point\n"
                  "denormal operand condition.");
    case MxCsr_RC:
        return tr("Bits 13 and 14 of the MXCSR register (the rounding control [RC] field) control how the results of SIMD floating-point instructions are rounded.");
    case LastError:
    {
        char dat[1024];
        LASTERROR* error;
        error = (LASTERROR*)registerValue(&wRegDumpStruct, LastError);
        if(DbgFunctions()->StringFormatInline(QString().sprintf("{winerror@%X}", error->code).toUtf8().constData(), sizeof(dat), dat))
            return dat;
        else
            return tr("The value of GetLastError(). This value is stored in the TEB.");
    }
    case LastStatus:
    {
        char dat[1024];
        LASTSTATUS* error;
        error = (LASTSTATUS*)registerValue(&wRegDumpStruct, LastStatus);
        if(DbgFunctions()->StringFormatInline(QString().sprintf("{ntstatus@%X}", error->code).toUtf8().constData(), sizeof(dat), dat))
            return dat;
        else
            return tr("The NTSTATUS in the LastStatusValue field of the TEB.");
    }
#ifdef _WIN64
    case GS:
        return tr("The TEB of the current thread can be accessed as an offset of segment register GS (x64).\nThe TEB can be used to get a lot of information on the process without calling Win32 API.");
#else   // x86
    case FS:
        return tr("The TEB of the current thread can be accessed as an offset of segment register FS (x86).\nThe TEB can be used to get a lot of information on the process without calling Win32 API.");
#endif  //_WIN64
#endif
    default:
      return QString();
  }
}

void RegistersViewA64::mousePressEvent(QMouseEvent* event) {
  if (!isActive) return;

  if (event->y() < yTopSpacing - mButtonHeight) {
    onChangeFPUViewAction();
  } else {
    // get mouse position
    const int y = (event->y() - yTopSpacing) / (double)mRowHeight;
    const int x = event->x() / (double)mCharWidth;

    REGISTER_NAME r;
    // do we find a corresponding register?
    if (identifyRegister(y, x, &r)) {
      mSelected = r;
      emit refresh();
    } else
      mSelected = UNKNOWN;
  }
}

void RegistersViewA64::mouseMoveEvent(QMouseEvent* event) {
  if (!isActive) {
    QScrollArea::mouseMoveEvent(event);
    setCursor(QCursor(Qt::ArrowCursor));
    return;
  }

  REGISTER_NAME r = UNKNOWN;
  QString registerHelpInformation;
  // do we find a corresponding register?
  if (identifyRegister((event->y() - yTopSpacing) / (double)mRowHeight,
                       event->x() / (double)mCharWidth, &r)) {
    registerHelpInformation = helpRegister(r).replace(" : ", ": ");
    setCursor(QCursor(Qt::PointingHandCursor));
  } else {
    registerHelpInformation = "";
    setCursor(QCursor(Qt::ArrowCursor));
  }
  if (!registerHelpInformation.isEmpty())
    QToolTip::showText(event->globalPos(), registerHelpInformation);
  else
    QToolTip::hideText();
  QScrollArea::mouseMoveEvent(event);
}

void RegistersViewA64::mouseDoubleClickEvent(QMouseEvent* event) {}

void RegistersViewA64::paintEvent(QPaintEvent* event) {
  Q_UNUSED(event);

  if (mChangeViewButton != NULL) {
    if (mShowFpu)
      mChangeViewButton->setText(tr("Hide NEON"));
    else
      mChangeViewButton->setText(tr("Show NEON"));
  }

  QPainter wPainter(this->viewport());
  wPainter.setFont(font());
  wPainter.fillRect(wPainter.viewport(),
                    QBrush(ConfigColor("RegistersBackgroundColor")));

  // Don't draw the registers if a program isn't actually running
  if (!isActive) return;

  // Iterate all registers
  for (auto itr = mRegisterMapping.begin(); itr != mRegisterMapping.end();
       itr++) {
    // Paint register at given position
    drawRegister(&wPainter, itr.key(),
                 registerValue(&wRegDumpStruct, itr.key()));
  }
}

void RegistersViewA64::keyPressEvent(QKeyEvent* event) {
  QScrollArea::keyPressEvent(event);
}

QSize RegistersViewA64::sizeHint() const {
  // 32 character width
  return QSize(32 * mCharWidth, this->viewport()->height());
}

void* RegistersViewA64::operator new(size_t size) {
  return _aligned_malloc(size, 16);
}

void RegistersViewA64::operator delete(void* p) { _aligned_free(p); }

/**
 * @brief                   Get the label associated with the register
 * @param register_selected the register
 * @return                  the label
 */
QString RegistersViewA64::getRegisterLabel(REGISTER_NAME register_selected) {
  char label_text[MAX_LABEL_SIZE] = "";
  char module_text[MAX_MODULE_SIZE] = "";
  char string_text[MAX_STRING_SIZE] = "";

  QString valueText =
      QString("%1")
          .arg((*((duint*)registerValue(&wRegDumpStruct, register_selected))),
               mRegisterPlaces[register_selected].valuesize, 16, QChar('0'))
          .toUpper();
  duint register_value =
      (*((duint*)registerValue(&wRegDumpStruct, register_selected)));
  QString newText = QString("");

  bool hasString = DbgGetStringAt(register_value, string_text);
  bool hasLabel = DbgGetLabelAt(register_value, SEG_DEFAULT, label_text);
  bool hasModule = DbgGetModuleAt(register_value, module_text);

  if (hasString && !mONLYMODULEANDLABELDISPLAY.contains(register_selected)) {
    newText = string_text;
  } else if (hasLabel && hasModule) {
    newText = "<" + QString(module_text) + "." + QString(label_text) + ">";
  } else if (hasModule) {
    newText = QString(module_text) + "." + valueText;
  } else if (hasLabel) {
    newText = "<" + QString(label_text) + ">";
  } else if (!mONLYMODULEANDLABELDISPLAY.contains(register_selected)) {
    if (register_value == (register_value & 0xFF)) {
      QChar c = QChar((char)register_value);
      if (c.isPrint()) {
        newText = QString("'%1'").arg((char)register_value);
      }
    } else if (register_value == (register_value & 0xFFF))  // UNICODE?
    {
      QChar c = QChar((wchar_t)register_value);
      if (c.isPrint()) {
        newText = "L'" + QString(c) + "'";
      }
    }
  }

  return std::move(newText);
}

/**
 * @brief RegistersViewA64::GetRegStringValueFromValue Get the textual
 * representation of the register value.
 * @param reg The name of the register
 * @param value The current value of the register
 * @return The textual representation of the register value
 *
 * This value does not return hex representation all the times for SIMD
 * registers. The actual representation of SIMD registers depends on the user
 * settings.
 */
QString RegistersViewA64::GetRegStringValueFromValue(REGISTER_NAME reg,
                                                  const char* value) {
  QString valueText;

  if (mUINTDISPLAY.contains(reg))
    valueText = QString("%1")
                    .arg((*((const duint*)value)),
                         mRegisterPlaces[reg].valuesize, 16, QChar('0'))
                    .toUpper();
  else if (mUSHORTDISPLAY.contains(reg))
    valueText = QString("%1")
                    .arg((*((const unsigned short*)value)),
                         mRegisterPlaces[reg].valuesize, 16, QChar('0'))
                    .toUpper();
  else if (mDWORDDISPLAY.contains(reg))
    valueText = QString("%1")
                    .arg((*((const DWORD*)value)),
                         mRegisterPlaces[reg].valuesize, 16, QChar('0'))
                    .toUpper();
  else if (mBOOLDISPLAY.contains(reg))
    valueText = QString("%1")
                    .arg((*((const bool*)value)),
                         mRegisterPlaces[reg].valuesize, 16, QChar('0'))
                    .toUpper();
  else if (mFIELDVALUE.contains(reg)) {
    if (mTAGWORD.contains(reg)) {
      valueText = QString("%1")
                      .arg((*((const unsigned short*)value)), 1, 16, QChar('0'))
                      .toUpper();
      valueText += QString(" (");
      valueText += GetTagWordStateString((*((const unsigned short*)value)));
      valueText += QString(")");
    }
#if 0
        if(reg == MxCsr_RC)
        {
            valueText = QString("%1").arg((* ((const unsigned short*) value)), 1, 16, QChar('0')).toUpper();
            valueText += QString(" (");
            valueText += GetMxCsrRCStateString((* ((const unsigned short*) value)));
            valueText += QString(")");
        }
        else if(reg == x87CW_RC)
        {
            valueText = QString("%1").arg((* ((const unsigned short*) value)), 1, 16, QChar('0')).toUpper();
            valueText += QString(" (");
            valueText += GetControlWordRCStateString((* ((const unsigned short*) value)));
            valueText += QString(")");
        }
        else if(reg == x87CW_PC)
        {
            valueText = QString("%1").arg((* ((const unsigned short*) value)), 1, 16, QChar('0')).toUpper();
            valueText += QString(" (");
            valueText += GetControlWordPCStateString((* ((const unsigned short*) value)));
            valueText += QString(")");
        }
        else if(reg == x87SW_TOP)
        {
            valueText = QString("%1").arg((* ((const unsigned short*) value)), 1, 16, QChar('0')).toUpper();
            valueText += QString(" (ST0=");
            valueText += GetStatusWordTOPStateString((* ((const unsigned short*) value)));
            valueText += QString(")");
        }
#endif
  }
#if 0
    else if(reg == LastError)
    {
        LASTERROR* data = (LASTERROR*)value;
        if(*data->name)
            valueText = QString().sprintf("%08X (%s)", data->code, data->name);
        else
            valueText = QString().sprintf("%08X", data->code);
        mRegisterPlaces[LastError].valuesize = valueText.length();
    }
    else if(reg == LastStatus)
    {
        LASTSTATUS* data = (LASTSTATUS*)value;
        if(*data->name)
            valueText = QString().sprintf("%08X (%s)", data->code, data->name);
        else
            valueText = QString().sprintf("%08X", data->code);
        mRegisterPlaces[LastStatus].valuesize = valueText.length();
    }
#endif
  else {
    SIZE_T size = GetSizeRegister(reg);
    bool bFpuRegistersLittleEndian =
        ConfigBool("Gui", "FpuRegistersLittleEndian");
    if (size != 0) {
      if (mFPUXMM.contains(reg))
        valueText = GetDataTypeString(value, size, enc_xmmword);
      else if (mFPUYMM.contains(reg))
        valueText = GetDataTypeString(value, size, enc_ymmword);
      else
        valueText = fillValue(value, size, bFpuRegistersLittleEndian);
    } else
      valueText = QString("???");
  }

  return std::move(valueText);
}

#define MxCsr_RC_NEAR 0
#define MxCsr_RC_NEGATIVE 1
#define MxCsr_RC_POSITIVE 2
#define MxCsr_RC_TOZERO 3

static STRING_VALUE_TABLE_t MxCsrRCValueStringTable[] = {
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Toward Zero"),
     MxCsr_RC_TOZERO},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Toward Positive"),
     MxCsr_RC_POSITIVE},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Toward Negative"),
     MxCsr_RC_NEGATIVE},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Round Near"),
     MxCsr_RC_NEAR}};
// WARNING: The following function is commented out because it is not used
// currently. If it is used again, it should be modified to keep working under
// internationized environment.
/*
unsigned int RegistersViewA64::GetMxCsrRCValueFromString(const char* string)
{
    int i;

    for(i = 0; i < (sizeof(MxCsrRCValueStringTable) /
sizeof(*MxCsrRCValueStringTable)); i++)
    {
        if(MxCsrRCValueStringTable[i].string == string)
            return MxCsrRCValueStringTable[i].value;
    }

    return i;
}
*/
QString RegistersViewA64::GetMxCsrRCStateString(unsigned short state) {
  int i;

  for (i = 0;
       i < (sizeof(MxCsrRCValueStringTable) / sizeof(*MxCsrRCValueStringTable));
       i++) {
    if (MxCsrRCValueStringTable[i].value == state)
      return QApplication::translate("RegistersViewA64_ConstantsOfRegisters",
                                     MxCsrRCValueStringTable[i].string);
  }

  return tr("Unknown");
}

#define x87CW_RC_NEAR 0
#define x87CW_RC_DOWN 1
#define x87CW_RC_UP 2
#define x87CW_RC_TRUNCATE 3

static STRING_VALUE_TABLE_t ControlWordRCValueStringTable[] = {
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Truncate"),
     x87CW_RC_TRUNCATE},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Round Up"),
     x87CW_RC_UP},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Round Down"),
     x87CW_RC_DOWN},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Round Near"),
     x87CW_RC_NEAR}};
// WARNING: The following function is commented out because it is not used
// currently. If it is used again, it should be modified to keep working under
// internationized environment.
/*
unsigned int RegistersViewA64::GetControlWordRCValueFromString(const char* string)
{
    int i;

    for(i = 0; i < (sizeof(ControlWordRCValueStringTable) /
sizeof(*ControlWordRCValueStringTable)); i++)
    {
        if(tr(ControlWordRCValueStringTable[i].string) == string)
            return ControlWordRCValueStringTable[i].value;
    }

    return i;
}
*/
QString RegistersViewA64::GetControlWordRCStateString(unsigned short state) {
  int i;

  for (i = 0; i < (sizeof(ControlWordRCValueStringTable) /
                   sizeof(*ControlWordRCValueStringTable));
       i++) {
    if (ControlWordRCValueStringTable[i].value == state)
      return QApplication::translate("RegistersViewA64_ConstantsOfRegisters",
                                     ControlWordRCValueStringTable[i].string);
  }

  return tr("Unknown");
}

#define x87SW_TOP_0 0
#define x87SW_TOP_1 1
#define x87SW_TOP_2 2
#define x87SW_TOP_3 3
#define x87SW_TOP_4 4
#define x87SW_TOP_5 5
#define x87SW_TOP_6 6
#define x87SW_TOP_7 7
// This string needs not to be internationalized.
static STRING_VALUE_TABLE_t StatusWordTOPValueStringTable[] = {
    {"x87r0", x87SW_TOP_0}, {"x87r1", x87SW_TOP_1}, {"x87r2", x87SW_TOP_2},
    {"x87r3", x87SW_TOP_3}, {"x87r4", x87SW_TOP_4}, {"x87r5", x87SW_TOP_5},
    {"x87r6", x87SW_TOP_6}, {"x87r7", x87SW_TOP_7}};
// WARNING: The following function is commented out because it is not used
// currently. If it is used again, it should be modified to keep working under
// internationized environment.
/*
unsigned int RegistersViewA64::GetStatusWordTOPValueFromString(const char* string)
{
    int i;

    for(i = 0; i < (sizeof(StatusWordTOPValueStringTable) /
sizeof(*StatusWordTOPValueStringTable)); i++)
    {
        if(StatusWordTOPValueStringTable[i].string == string)
            return StatusWordTOPValueStringTable[i].value;
    }

    return i;
}
*/
QString RegistersViewA64::GetStatusWordTOPStateString(unsigned short state) {
  int i;

  for (i = 0; i < (sizeof(StatusWordTOPValueStringTable) /
                   sizeof(*StatusWordTOPValueStringTable));
       i++) {
    if (StatusWordTOPValueStringTable[i].value == state)
      return StatusWordTOPValueStringTable[i].string;
  }

  return tr("Unknown");
}

#define x87CW_PC_REAL4 0
#define x87CW_PC_NOTUSED 1
#define x87CW_PC_REAL8 2
#define x87CW_PC_REAL10 3

static STRING_VALUE_TABLE_t ControlWordPCValueStringTable[] = {
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Real4"),
     x87CW_PC_REAL4},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Not Used"),
     x87CW_PC_NOTUSED},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Real8"),
     x87CW_PC_REAL8},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Real10"),
     x87CW_PC_REAL10}};
/*
//WARNING: The following function is commented out because it is not used
currently. If it is used again, it should be modified to keep working under
internationized environment. unsigned int
RegistersViewA64::GetControlWordPCValueFromString(const char* string)
{
    int i;

    for(i = 0; i < (sizeof(ControlWordPCValueStringTable) /
sizeof(*ControlWordPCValueStringTable)); i++)
    {
        if(tr(ControlWordPCValueStringTable[i].string) == string)
            return ControlWordPCValueStringTable[i].value;
    }

    return i;
}
*/

QString RegistersViewA64::GetControlWordPCStateString(unsigned short state) {
  int i;

  for (i = 0; i < (sizeof(ControlWordPCValueStringTable) /
                   sizeof(*ControlWordPCValueStringTable));
       i++) {
    if (ControlWordPCValueStringTable[i].value == state)
      return QApplication::translate("RegistersViewA64_ConstantsOfRegisters",
                                     ControlWordPCValueStringTable[i].string);
  }

  return tr("Unknown");
}

#define X87FPU_TAGWORD_NONZERO 0
#define X87FPU_TAGWORD_ZERO 1
#define X87FPU_TAGWORD_SPECIAL 2
#define X87FPU_TAGWORD_EMPTY 3

static STRING_VALUE_TABLE_t TagWordValueStringTable[] = {
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Nonzero"),
     X87FPU_TAGWORD_NONZERO},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Zero"),
     X87FPU_TAGWORD_ZERO},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Special"),
     X87FPU_TAGWORD_SPECIAL},
    {QT_TRANSLATE_NOOP("RegistersViewA64_ConstantsOfRegisters", "Empty"),
     X87FPU_TAGWORD_EMPTY}};
// WARNING: The following function is commented out because it is not used
// currently. If it is used again, it should be modified to keep working under
// internationized environment.
/*
unsigned int RegistersViewA64::GetTagWordValueFromString(const char* string)
{
    int i;

    for(i = 0; i < (sizeof(TagWordValueStringTable) /
sizeof(*TagWordValueStringTable)); i++)
    {
        if(tr(TagWordValueStringTable[i].string) == string)
            return TagWordValueStringTable[i].value;
    }

    return i;
}

*/
QString RegistersViewA64::GetTagWordStateString(unsigned short state) {
  int i;

  for (i = 0;
       i < (sizeof(TagWordValueStringTable) / sizeof(*TagWordValueStringTable));
       i++) {
    if (TagWordValueStringTable[i].value == state)
      return QApplication::translate("RegistersViewA64_ConstantsOfRegisters",
                                     TagWordValueStringTable[i].string);
  }

  return tr("Unknown");
}

void RegistersViewA64::drawRegister(QPainter* p, REGISTER_NAME reg, char* value) {
  QFontMetrics fontMetrics(font());
  // is the register-id known?
  if (mRegisterMapping.contains(reg)) {
    // padding to the left is at least one character (looks better)
    int x = mCharWidth * (1 + mRegisterPlaces[reg].start);
    int ySpace = yTopSpacing;
    if (mVScrollOffset != 0) ySpace = 0;
    int y = mRowHeight * (mRegisterPlaces[reg].line + mVScrollOffset) + ySpace;

    // draw raster
    /*
    p->save();
    p->setPen(QColor("#FF0000"));
    p->drawLine(0, y, this->viewport()->width(), y);
    p->restore();
    */

    // draw name of value
    int width = fontMetrics.width(mRegisterMapping[reg]);

    // set the color of the register label
#ifdef _WIN64
    switch (reg) {
      case X0 + 0:  // arg1
      case X0 + 1:  // arg2
      case X0 + 2:  // arg3
      case X0 + 3:  // arg4
      case X0 + 4:  // arg5
      case X0 + 5:  // arg6
      case X0 + 6:  // arg7
      case X0 + 7:  // arg8
      case Q0 + 0:
      case Q0 + 1:
      case Q0 + 2:
      case Q0 + 3:
      case Q0 + 4:
      case Q0 + 5:
      case Q0 + 6:
      case Q0 + 7:
        p->setPen(ConfigColor("RegistersArgumentLabelColor"));
        break;
      default:
#endif  //_WIN64
        p->setPen(ConfigColor("RegistersLabelColor"));
#ifdef _WIN64
        break;
    }
#endif  //_WIN64

    // draw the register name
    auto regName = mRegisterMapping[reg];
    p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, regName);

    // highlight the register based on access
    uint8_t highlight = 0;
    for (const auto& reg : mHighlightRegs) {
      if (!ZydisTokenizer::tokenTextPoolEquals(regName, reg.first)) continue;
      highlight = reg.second;
      break;
    }
    if (highlight) {
      const char* name = "";
      switch (highlight & ~(Zydis::RAIImplicit | Zydis::RAIExplicit)) {
        case Zydis::RAIRead:
          name = "RegistersHighlightReadColor";
          break;
        case Zydis::RAIWrite:
          name = "RegistersHighlightWriteColor";
          break;
        case Zydis::RAIRead | Zydis::RAIWrite:
          name = "RegistersHighlightReadWriteColor";
          break;
      }
      auto highlightColor = ConfigColor(name);
      if (highlightColor.alpha()) {
        QPen highlightPen(highlightColor);
        highlightPen.setWidth(2);
        p->setPen(highlightPen);
        p->drawLine(x + 1, y + mRowHeight - 1,
                    x + mCharWidth * regName.length() - 1, y + mRowHeight - 1);
      }
    }

    x += (mRegisterPlaces[reg].labelwidth) * mCharWidth;
    // p->drawText(offset,mRowHeight*(mRegisterPlaces[reg].line+1),mRegisterMapping[reg]);

    // set highlighting
    if (isActive && mRegisterUpdates.contains(reg))
      p->setPen(ConfigColor("RegistersModifiedColor"));
    else
      p->setPen(ConfigColor("RegistersColor"));

    // get register value
    QString valueText = GetRegStringValueFromValue(reg, value);

    // selection
    width = fontMetrics.width(valueText);
    if (mSelected == reg) {
      p->fillRect(x, y, width, mRowHeight,
                  QBrush(ConfigColor("RegistersSelectionColor")));
      // p->fillRect(QRect(x + (mRegisterPlaces[reg].labelwidth)*mCharWidth
      // ,mRowHeight*(mRegisterPlaces[reg].line)+2,
      // mRegisterPlaces[reg].valuesize*mCharWidth, mRowHeight),
      // QBrush(ConfigColor("RegistersSelectionColor")));
    }

    // draw value
    p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, valueText);
    // p->drawText(x + (mRegisterPlaces[reg].labelwidth)*mCharWidth
    // ,mRowHeight*(mRegisterPlaces[reg].line+1),QString("%1").arg(value,
    // mRegisterPlaces[reg].valuesize, 16, QChar('0')).toUpper());

    x += width;

#if 0
        if(mFPUx87_80BITSDISPLAY.contains(reg) && isActive)
        {
            p->setPen(ConfigColor("RegistersExtraInfoColor"));
            x += 1 * mCharWidth; //1 space
            QString newText;
            if(mRegisterUpdates.contains(x87SW_TOP))
                p->setPen(ConfigColor("RegistersModifiedColor"));

            if(reg >= x87r0 && reg <= x87r7)
            {
                newText = QString("ST%1 ").arg(((X87FPUREGISTER*) registerValue(&wRegDumpStruct, reg))->st_value);
            }
            else
            {
                newText = QString("x87r%1 ").arg((wRegDumpStruct.x87StatusWordFields.TOP + (reg - x87st0)) & 7);
            }
            width = fontMetrics.width(newText);
            p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, newText);

            x += width;

            newText = QString("");

            p->setPen(ConfigColor("RegistersExtraInfoColor"));

            if(reg >= x87r0 && reg <= x87r7 && mRegisterUpdates.contains((REGISTER_NAME)(x87TW_0 + (reg - x87r0))))
                p->setPen(ConfigColor("RegistersModifiedColor"));

            newText += GetTagWordStateString(((X87FPUREGISTER*) registerValue(&wRegDumpStruct, reg))->tag) + QString(" ");

            width = fontMetrics.width(newText);
            p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, newText);

            x += width;

            newText = QString("");

            p->setPen(ConfigColor("RegistersExtraInfoColor"));

            if(isActive && mRegisterUpdates.contains(reg))
                p->setPen(ConfigColor("RegistersModifiedColor"));

            newText += ToLongDoubleString(((X87FPUREGISTER*) registerValue(&wRegDumpStruct, reg))->data);
            width = fontMetrics.width(newText);
            p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, newText);
        }
#endif
    // do we have a label ?
    if (mLABELDISPLAY.contains(reg)) {
      x += 5 * mCharWidth;  // 5 spaces

      QString newText = getRegisterLabel(reg);

      // are there additional informations?
      if (newText != "") {
        width = fontMetrics.width(newText);
        p->setPen(ConfigColor("RegistersExtraInfoColor"));
        p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, newText);
        // p->drawText(x,mRowHeight*(mRegisterPlaces[reg].line+1),newText);
      }
    }
  }
}

void RegistersViewA64::appendRegister(QString& text, REGISTER_NAME reg,
                                   const char* name64, const char* name32) {
  QString symbol;
#ifdef _WIN64
  Q_UNUSED(name32);
  text.append(name64);
#else   // x86
  Q_UNUSED(name64);
  text.append(name32);
#endif  //_WIN64
  text.append(
      GetRegStringValueFromValue(reg, registerValue(&wRegDumpStruct, reg)));
  symbol = getRegisterLabel(reg);
  if (symbol != "") {
    text.append("     ");
    text.append(symbol);
  }
  text.append("\r\n");
}

void RegistersViewA64::onChangeFPUViewAction() { ShowFPU(!mShowFpu); }

void RegistersViewA64::onCopyAllAction() {
  QString text;
#if 0
    appendRegister(text, REGISTER_NAME::CAX, "RAX : ", "EAX : ");
    appendRegister(text, REGISTER_NAME::CBX, "RBX : ", "EBX : ");
    appendRegister(text, REGISTER_NAME::CCX, "RCX : ", "ECX : ");
    appendRegister(text, REGISTER_NAME::CDX, "RDX : ", "EDX : ");
    appendRegister(text, REGISTER_NAME::CBP, "RBP : ", "EBP : ");
    appendRegister(text, REGISTER_NAME::CSP, "RSP : ", "ESP : ");
    appendRegister(text, REGISTER_NAME::CSI, "RSI : ", "ESI : ");
    appendRegister(text, REGISTER_NAME::CDI, "RDI : ", "EDI : ");
#ifdef _WIN64
    appendRegister(text, REGISTER_NAME::R8, "R8  : ", "R8  : ");
    appendRegister(text, REGISTER_NAME::R9, "R9  : ", "R9  : ");
    appendRegister(text, REGISTER_NAME::R10, "R10 : ", "R10 : ");
    appendRegister(text, REGISTER_NAME::R11, "R11 : ", "R11 : ");
    appendRegister(text, REGISTER_NAME::R12, "R12 : ", "R12 : ");
    appendRegister(text, REGISTER_NAME::R13, "R13 : ", "R13 : ");
    appendRegister(text, REGISTER_NAME::R14, "R14 : ", "R14 : ");
    appendRegister(text, REGISTER_NAME::R15, "R15 : ", "R15 : ");
#endif
#else
  for (int i = 0; i < 10; i++) {
    char regname[16];
    sprintf(regname, "x%d  : ", i);
    appendRegister(text, i, regname, regname);
  }
  for (int i = 10; i < 30; i++) {
    char regname[16];
    sprintf(regname, "x%d : ", i);
    appendRegister(text, i, regname, regname);
  }
  appendRegister(text, LR, "lr  : ", "lr  : ");
  appendRegister(text, SP, "sp  : ", "sp  : ");
#endif
  appendRegister(text, PC, "pc  : ", "pc  : ");
  appendRegister(text, FLAGS, "flags : ", "flags : ");
  appendRegister(text, N, "NF : ", "NF : ");
  appendRegister(text, Z, "ZF : ", "ZF : ");
  appendRegister(text, C, "CF : ", "CF : ");
  appendRegister(text, V, "VF : ", "VF : ");
#if 0
    appendRegister(text, REGISTER_NAME::SF, "SF : ", "SF : ");
    appendRegister(text, REGISTER_NAME::TF, "TF : ", "TF : ");
    appendRegister(text, REGISTER_NAME::AF, "AF : ", "AF : ");
    appendRegister(text, REGISTER_NAME::DF, "DF : ", "DF : ");
    appendRegister(text, REGISTER_NAME::IF, "IF : ", "IF : ");
    appendRegister(text, REGISTER_NAME::LastError, "LastError : ", "LastError : ");
    appendRegister(text, REGISTER_NAME::LastStatus, "LastStatus : ", "LastStatus : ");
    appendRegister(text, REGISTER_NAME::GS, "GS : ", "GS : ");
    appendRegister(text, REGISTER_NAME::ES, "ES : ", "ES : ");
    appendRegister(text, REGISTER_NAME::CS, "CS : ", "CS : ");
    appendRegister(text, REGISTER_NAME::FS, "FS : ", "FS : ");
    appendRegister(text, REGISTER_NAME::DS, "DS : ", "DS : ");
    appendRegister(text, REGISTER_NAME::SS, "SS : ", "SS : ");
    if(mShowFpu)
    {
        switch(mFpuMode)
        {
        case 0:
            appendRegister(text, REGISTER_NAME::x87st0, "ST(0) : ", "ST(0) : ");
            appendRegister(text, REGISTER_NAME::x87st1, "ST(1) : ", "ST(1) : ");
            appendRegister(text, REGISTER_NAME::x87st2, "ST(2) : ", "ST(2) : ");
            appendRegister(text, REGISTER_NAME::x87st3, "ST(3) : ", "ST(3) : ");
            appendRegister(text, REGISTER_NAME::x87st4, "ST(4) : ", "ST(4) : ");
            appendRegister(text, REGISTER_NAME::x87st5, "ST(5) : ", "ST(5) : ");
            appendRegister(text, REGISTER_NAME::x87st6, "ST(6) : ", "ST(6) : ");
            appendRegister(text, REGISTER_NAME::x87st7, "ST(7) : ", "ST(7) : ");
            break;
        case 1:
            appendRegister(text, REGISTER_NAME::x87r0, "x87r0 : ", "x87r0 : ");
            appendRegister(text, REGISTER_NAME::x87r1, "x87r1 : ", "x87r1 : ");
            appendRegister(text, REGISTER_NAME::x87r2, "x87r2 : ", "x87r2 : ");
            appendRegister(text, REGISTER_NAME::x87r3, "x87r3 : ", "x87r3 : ");
            appendRegister(text, REGISTER_NAME::x87r4, "x87r4 : ", "x87r4 : ");
            appendRegister(text, REGISTER_NAME::x87r5, "x87r5 : ", "x87r5 : ");
            appendRegister(text, REGISTER_NAME::x87r6, "x87r6 : ", "x87r6 : ");
            appendRegister(text, REGISTER_NAME::x87r7, "x87r7 : ", "x87r7 : ");
            break;
        case 2:
            appendRegister(text, REGISTER_NAME::MM0, "MM0 : ", "MM0 : ");
            appendRegister(text, REGISTER_NAME::MM1, "MM1 : ", "MM1 : ");
            appendRegister(text, REGISTER_NAME::MM2, "MM2 : ", "MM2 : ");
            appendRegister(text, REGISTER_NAME::MM3, "MM3 : ", "MM3 : ");
            appendRegister(text, REGISTER_NAME::MM4, "MM4 : ", "MM4 : ");
            appendRegister(text, REGISTER_NAME::MM5, "MM5 : ", "MM5 : ");
            appendRegister(text, REGISTER_NAME::MM6, "MM6 : ", "MM6 : ");
            appendRegister(text, REGISTER_NAME::MM7, "MM7 : ", "MM7 : ");
            break;
        }
        appendRegister(text, REGISTER_NAME::x87TagWord, "x87TagWord : ", "x87TagWord : ");
        appendRegister(text, REGISTER_NAME::x87ControlWord, "x87ControlWord : ", "x87ControlWord : ");
        appendRegister(text, REGISTER_NAME::x87StatusWord, "x87StatusWord : ", "x87StatusWord : ");
        appendRegister(text, REGISTER_NAME::x87TW_0, "x87TW_0 : ", "x87TW_0 : ");
        appendRegister(text, REGISTER_NAME::x87TW_1, "x87TW_1 : ", "x87TW_1 : ");
        appendRegister(text, REGISTER_NAME::x87TW_2, "x87TW_2 : ", "x87TW_2 : ");
        appendRegister(text, REGISTER_NAME::x87TW_3, "x87TW_3 : ", "x87TW_3 : ");
        appendRegister(text, REGISTER_NAME::x87TW_4, "x87TW_4 : ", "x87TW_4 : ");
        appendRegister(text, REGISTER_NAME::x87TW_5, "x87TW_5 : ", "x87TW_5 : ");
        appendRegister(text, REGISTER_NAME::x87TW_6, "x87TW_6 : ", "x87TW_6 : ");
        appendRegister(text, REGISTER_NAME::x87TW_7, "x87TW_7 : ", "x87TW_7 : ");
        appendRegister(text, REGISTER_NAME::x87SW_B, "x87SW_B : ", "x87SW_B : ");
        appendRegister(text, REGISTER_NAME::x87SW_C3, "x87SW_C3 : ", "x87SW_C3 : ");
        appendRegister(text, REGISTER_NAME::x87SW_TOP, "x87SW_TOP : ", "x87SW_TOP : ");
        appendRegister(text, REGISTER_NAME::x87SW_C2, "x87SW_C2 : ", "x87SW_C2 : ");
        appendRegister(text, REGISTER_NAME::x87SW_C1, "x87SW_C1 : ", "x87SW_C1 : ");
        appendRegister(text, REGISTER_NAME::x87SW_O, "x87SW_O : ", "x87SW_O : ");
        appendRegister(text, REGISTER_NAME::x87SW_ES, "x87SW_ES : ", "x87SW_ES : ");
        appendRegister(text, REGISTER_NAME::x87SW_SF, "x87SW_SF : ", "x87SW_SF : ");
        appendRegister(text, REGISTER_NAME::x87SW_P, "x87SW_P : ", "x87SW_P : ");
        appendRegister(text, REGISTER_NAME::x87SW_U, "x87SW_U : ", "x87SW_U : ");
        appendRegister(text, REGISTER_NAME::x87SW_Z, "x87SW_Z : ", "x87SW_Z : ");
        appendRegister(text, REGISTER_NAME::x87SW_D, "x87SW_D : ", "x87SW_D : ");
        appendRegister(text, REGISTER_NAME::x87SW_I, "x87SW_I : ", "x87SW_I : ");
        appendRegister(text, REGISTER_NAME::x87SW_C0, "x87SW_C0 : ", "x87SW_C0 : ");
        appendRegister(text, REGISTER_NAME::x87CW_IC, "x87CW_IC : ", "x87CW_IC : ");
        appendRegister(text, REGISTER_NAME::x87CW_RC, "x87CW_RC : ", "x87CW_RC : ");
        appendRegister(text, REGISTER_NAME::x87CW_PC, "x87CW_PC : ", "x87CW_PC : ");
        appendRegister(text, REGISTER_NAME::x87CW_PM, "x87CW_PM : ", "x87CW_PM : ");
        appendRegister(text, REGISTER_NAME::x87CW_UM, "x87CW_UM : ", "x87CW_UM : ");
        appendRegister(text, REGISTER_NAME::x87CW_OM, "x87CW_OM : ", "x87CW_OM : ");
        appendRegister(text, REGISTER_NAME::x87CW_ZM, "x87CW_ZM : ", "x87CW_ZM : ");
        appendRegister(text, REGISTER_NAME::x87CW_DM, "x87CW_DM : ", "x87CW_DM : ");
        appendRegister(text, REGISTER_NAME::x87CW_IM, "x87CW_IM : ", "x87CW_IM : ");
        appendRegister(text, REGISTER_NAME::MxCsr, "MxCsr : ", "MxCsr : ");
        appendRegister(text, REGISTER_NAME::MxCsr_FZ, "MxCsr_FZ : ", "MxCsr_FZ : ");
        appendRegister(text, REGISTER_NAME::MxCsr_PM, "MxCsr_PM : ", "MxCsr_PM : ");
        appendRegister(text, REGISTER_NAME::MxCsr_UM, "MxCsr_UM : ", "MxCsr_UM : ");
        appendRegister(text, REGISTER_NAME::MxCsr_OM, "MxCsr_OM : ", "MxCsr_OM : ");
        appendRegister(text, REGISTER_NAME::MxCsr_ZM, "MxCsr_ZM : ", "MxCsr_ZM : ");
        appendRegister(text, REGISTER_NAME::MxCsr_IM, "MxCsr_IM : ", "MxCsr_IM : ");
        appendRegister(text, REGISTER_NAME::MxCsr_DM, "MxCsr_DM : ", "MxCsr_DM : ");
        appendRegister(text, REGISTER_NAME::MxCsr_DAZ, "MxCsr_DAZ : ", "MxCsr_DAZ : ");
        appendRegister(text, REGISTER_NAME::MxCsr_PE, "MxCsr_PE : ", "MxCsr_PE : ");
        appendRegister(text, REGISTER_NAME::MxCsr_UE, "MxCsr_UE : ", "MxCsr_UE : ");
        appendRegister(text, REGISTER_NAME::MxCsr_OE, "MxCsr_OE : ", "MxCsr_OE : ");
        appendRegister(text, REGISTER_NAME::MxCsr_ZE, "MxCsr_ZE : ", "MxCsr_ZE : ");
        appendRegister(text, REGISTER_NAME::MxCsr_DE, "MxCsr_DE : ", "MxCsr_DE : ");
        appendRegister(text, REGISTER_NAME::MxCsr_IE, "MxCsr_IE : ", "MxCsr_IE : ");
        appendRegister(text, REGISTER_NAME::MxCsr_RC, "MxCsr_RC : ", "MxCsr_RC : ");
        appendRegister(text, REGISTER_NAME::XMM0, "XMM0  : ", "XMM0  : ");
        appendRegister(text, REGISTER_NAME::XMM1, "XMM1  : ", "XMM1  : ");
        appendRegister(text, REGISTER_NAME::XMM2, "XMM2  : ", "XMM2  : ");
        appendRegister(text, REGISTER_NAME::XMM3, "XMM3  : ", "XMM3  : ");
        appendRegister(text, REGISTER_NAME::XMM4, "XMM4  : ", "XMM4  : ");
        appendRegister(text, REGISTER_NAME::XMM5, "XMM5  : ", "XMM5  : ");
        appendRegister(text, REGISTER_NAME::XMM6, "XMM6  : ", "XMM6  : ");
        appendRegister(text, REGISTER_NAME::XMM7, "XMM7  : ", "XMM7  : ");
#ifdef _WIN64
        appendRegister(text, REGISTER_NAME::XMM8, "XMM8  : ", "XMM8  : ");
        appendRegister(text, REGISTER_NAME::XMM9, "XMM9  : ", "XMM9  : ");
        appendRegister(text, REGISTER_NAME::XMM10, "XMM10 : ", "XMM10 : ");
        appendRegister(text, REGISTER_NAME::XMM11, "XMM11 : ", "XMM11 : ");
        appendRegister(text, REGISTER_NAME::XMM12, "XMM12 : ", "XMM12 : ");
        appendRegister(text, REGISTER_NAME::XMM13, "XMM13 : ", "XMM13 : ");
        appendRegister(text, REGISTER_NAME::XMM14, "XMM14 : ", "XMM14 : ");
        appendRegister(text, REGISTER_NAME::XMM15, "XMM15 : ", "XMM15 : ");
#endif
        appendRegister(text, REGISTER_NAME::YMM0, "YMM0  : ", "YMM0  : ");
        appendRegister(text, REGISTER_NAME::YMM1, "YMM1  : ", "YMM1  : ");
        appendRegister(text, REGISTER_NAME::YMM2, "YMM2  : ", "YMM2  : ");
        appendRegister(text, REGISTER_NAME::YMM3, "YMM3  : ", "YMM3  : ");
        appendRegister(text, REGISTER_NAME::YMM4, "YMM4  : ", "YMM4  : ");
        appendRegister(text, REGISTER_NAME::YMM5, "YMM5  : ", "YMM5  : ");
        appendRegister(text, REGISTER_NAME::YMM6, "YMM6  : ", "YMM6  : ");
        appendRegister(text, REGISTER_NAME::YMM7, "YMM7  : ", "YMM7  : ");
#ifdef _WIN64
        appendRegister(text, REGISTER_NAME::YMM8, "YMM8  : ", "YMM8  : ");
        appendRegister(text, REGISTER_NAME::YMM9, "YMM9  : ", "YMM9  : ");
        appendRegister(text, REGISTER_NAME::YMM10, "YMM10 : ", "YMM10 : ");
        appendRegister(text, REGISTER_NAME::YMM11, "YMM11 : ", "YMM11 : ");
        appendRegister(text, REGISTER_NAME::YMM12, "YMM12 : ", "YMM12 : ");
        appendRegister(text, REGISTER_NAME::YMM13, "YMM13 : ", "YMM13 : ");
        appendRegister(text, REGISTER_NAME::YMM14, "YMM14 : ", "YMM14 : ");
        appendRegister(text, REGISTER_NAME::YMM15, "YMM15 : ", "YMM15 : ");
#endif
    }
    appendRegister(text, REGISTER_NAME::DR0, "DR0 : ", "DR0 : ");
    appendRegister(text, REGISTER_NAME::DR1, "DR1 : ", "DR1 : ");
    appendRegister(text, REGISTER_NAME::DR2, "DR2 : ", "DR2 : ");
    appendRegister(text, REGISTER_NAME::DR3, "DR3 : ", "DR3 : ");
    appendRegister(text, REGISTER_NAME::DR6, "DR6 : ", "DR6 : ");
    appendRegister(text, REGISTER_NAME::DR7, "DR7 : ", "DR7 : ");
#else
  for (int i = 0; i < 10; i++) {
    char regname[16];
    sprintf(regname, "q%d  : ", i);
    appendRegister(text, Q0 + i, regname, regname);
  }
  for (int i = 10; i < 30; i++) {
    char regname[16];
    sprintf(regname, "q%d : ", i);
    appendRegister(text, Q0 + i, regname, regname);
  }
#endif
  Bridge::CopyToClipboard(text);
}

void RegistersViewA64::debugStateChangedSlot(DBGSTATE state) {}

void RegistersViewA64::reload() { this->viewport()->update(); }

SIZE_T RegistersViewA64::GetSizeRegister(const REGISTER_NAME reg_name) {
  SIZE_T size;

  if (mUINTDISPLAY.contains(reg_name))
    size = sizeof(duint);
  else if (mUSHORTDISPLAY.contains(reg_name) || mFIELDVALUE.contains(reg_name))
    size = sizeof(unsigned short);
  else if (mDWORDDISPLAY.contains(reg_name))
    size = sizeof(DWORD);
  else if (mBOOLDISPLAY.contains(reg_name))
    size = sizeof(bool);
  else if (mFPUx87_80BITSDISPLAY.contains(reg_name))
    size = 10;
  else if (mFPUMMX.contains(reg_name))
    size = 8;
  else if (mFPUXMM.contains(reg_name))
    size = 16;
  else if (mFPUYMM.contains(reg_name))
    size = 32;
#if 0
    else if(reg_name == LastError)
        size = sizeof(DWORD);
    else if(reg_name == LastStatus)
        size = sizeof(NTSTATUS);
#endif
  else
    size = 0;

  return size;
}

int RegistersViewA64::CompareRegisters(const REGISTER_NAME reg_name,
                                    REGDUMP* regdump1, REGDUMP* regdump2) {
  SIZE_T size = GetSizeRegister(reg_name);
  char* reg1_data = registerValue(regdump1, reg_name);
  char* reg2_data = registerValue(regdump2, reg_name);

  if (size != 0) return memcmp(reg1_data, reg2_data, size);

  return -1;
}

char* RegistersViewA64::registerValue(const REGDUMP* regdraw,
                                   const REGISTER_NAME reg) {
  static int null_value = 0;
  // this is probably the most efficient general method to access the values of
  // the struct
  // TODO: add an array with something like: return array[reg].data, this is
  // more fast :-)
#if 0
    switch(reg)
    {
    case CAX:
        return (char*) &regd->regcontext.cax;
    case CBX:
        return (char*) &regd->regcontext.cbx;
    case CCX:
        return (char*) &regd->regcontext.ccx;
    case CDX:
        return (char*) &regd->regcontext.cdx;
    case CSI:
        return (char*) &regd->regcontext.csi;
    case CDI:
        return (char*) &regd->regcontext.cdi;
    case CBP:
        return (char*) &regd->regcontext.cbp;
    case CSP:
        return (char*) &regd->regcontext.csp;

    case CIP:
        return (char*) &regd->regcontext.cip;
    case EFLAGS:
        return (char*) &regd->regcontext.eflags;
#ifdef _WIN64
    case R8:
        return (char*) &regd->regcontext.r8;
    case R9:
        return (char*) &regd->regcontext.r9;
    case R10:
        return (char*) &regd->regcontext.r10;
    case R11:
        return (char*) &regd->regcontext.r11;
    case R12:
        return (char*) &regd->regcontext.r12;
    case R13:
        return (char*) &regd->regcontext.r13;
    case R14:
        return (char*) &regd->regcontext.r14;
    case R15:
        return (char*) &regd->regcontext.r15;
#endif
    // CF,PF,AF,ZF,SF,TF,IF,DF,OF
    case CF:
        return (char*) &regd->flags.c;
    case PF:
        return (char*) &regd->flags.p;
    case AF:
        return (char*) &regd->flags.a;
    case ZF:
        return (char*) &regd->flags.z;
    case SF:
        return (char*) &regd->flags.s;
    case TF:
        return (char*) &regd->flags.t;
    case IF:
        return (char*) &regd->flags.i;
    case DF:
        return (char*) &regd->flags.d;
    case OF:
        return (char*) &regd->flags.o;

    // GS,FS,ES,DS,CS,SS
    case GS:
        return (char*) &regd->regcontext.gs;
    case FS:
        return (char*) &regd->regcontext.fs;
    case ES:
        return (char*) &regd->regcontext.es;
    case DS:
        return (char*) &regd->regcontext.ds;
    case CS:
        return (char*) &regd->regcontext.cs;
    case SS:
        return (char*) &regd->regcontext.ss;

    case LastError:
        return (char*) &regd->lastError;
    case LastStatus:
        return (char*) &regd->lastStatus;

    case DR0:
        return (char*) &regd->regcontext.dr0;
    case DR1:
        return (char*) &regd->regcontext.dr1;
    case DR2:
        return (char*) &regd->regcontext.dr2;
    case DR3:
        return (char*) &regd->regcontext.dr3;
    case DR6:
        return (char*) &regd->regcontext.dr6;
    case DR7:
        return (char*) &regd->regcontext.dr7;

    case MM0:
        return (char*) &regd->mmx[0];
    case MM1:
        return (char*) &regd->mmx[1];
    case MM2:
        return (char*) &regd->mmx[2];
    case MM3:
        return (char*) &regd->mmx[3];
    case MM4:
        return (char*) &regd->mmx[4];
    case MM5:
        return (char*) &regd->mmx[5];
    case MM6:
        return (char*) &regd->mmx[6];
    case MM7:
        return (char*) &regd->mmx[7];

    case x87r0:
        return (char*) &regd->x87FPURegisters[0];
    case x87r1:
        return (char*) &regd->x87FPURegisters[1];
    case x87r2:
        return (char*) &regd->x87FPURegisters[2];
    case x87r3:
        return (char*) &regd->x87FPURegisters[3];
    case x87r4:
        return (char*) &regd->x87FPURegisters[4];
    case x87r5:
        return (char*) &regd->x87FPURegisters[5];
    case x87r6:
        return (char*) &regd->x87FPURegisters[6];
    case x87r7:
        return (char*) &regd->x87FPURegisters[7];

    case x87st0:
        return (char*) &regd->x87FPURegisters[regd->x87StatusWordFields.TOP & 7];
    case x87st1:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 1) & 7];
    case x87st2:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 2) & 7];
    case x87st3:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 3) & 7];
    case x87st4:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 4) & 7];
    case x87st5:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 5) & 7];
    case x87st6:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 6) & 7];
    case x87st7:
        return (char*) &regd->x87FPURegisters[(regd->x87StatusWordFields.TOP + 7) & 7];

    case x87TagWord:
        return (char*) &regd->regcontext.x87fpu.TagWord;

    case x87ControlWord:
        return (char*) &regd->regcontext.x87fpu.ControlWord;

    case x87TW_0:
        return (char*) &regd->x87FPURegisters[0].tag;
    case x87TW_1:
        return (char*) &regd->x87FPURegisters[1].tag;
    case x87TW_2:
        return (char*) &regd->x87FPURegisters[2].tag;
    case x87TW_3:
        return (char*) &regd->x87FPURegisters[3].tag;
    case x87TW_4:
        return (char*) &regd->x87FPURegisters[4].tag;
    case x87TW_5:
        return (char*) &regd->x87FPURegisters[5].tag;
    case x87TW_6:
        return (char*) &regd->x87FPURegisters[6].tag;
    case x87TW_7:
        return (char*) &regd->x87FPURegisters[7].tag;

    case x87CW_IC:
        return (char*) &regd->x87ControlWordFields.IC;
    case x87CW_PM:
        return (char*) &regd->x87ControlWordFields.PM;
    case x87CW_UM:
        return (char*) &regd->x87ControlWordFields.UM;
    case x87CW_OM:
        return (char*) &regd->x87ControlWordFields.OM;
    case x87CW_ZM:
        return (char*) &regd->x87ControlWordFields.ZM;
    case x87CW_DM:
        return (char*) &regd->x87ControlWordFields.DM;
    case x87CW_IM:
        return (char*) &regd->x87ControlWordFields.IM;
    case x87CW_RC:
        return (char*) &regd->x87ControlWordFields.RC;
    case x87CW_PC:
        return (char*) &regd->x87ControlWordFields.PC;

    case x87StatusWord:
        return (char*) &regd->regcontext.x87fpu.StatusWord;

    case x87SW_B:
        return (char*) &regd->x87StatusWordFields.B;
    case x87SW_C3:
        return (char*) &regd->x87StatusWordFields.C3;
    case x87SW_C2:
        return (char*) &regd->x87StatusWordFields.C2;
    case x87SW_C1:
        return (char*) &regd->x87StatusWordFields.C1;
    case x87SW_O:
        return (char*) &regd->x87StatusWordFields.O;
    case x87SW_ES:
        return (char*) &regd->x87StatusWordFields.ES;
    case x87SW_SF:
        return (char*) &regd->x87StatusWordFields.SF;
    case x87SW_P:
        return (char*) &regd->x87StatusWordFields.P;
    case x87SW_U:
        return (char*) &regd->x87StatusWordFields.U;
    case x87SW_Z:
        return (char*) &regd->x87StatusWordFields.Z;
    case x87SW_D:
        return (char*) &regd->x87StatusWordFields.D;
    case x87SW_I:
        return (char*) &regd->x87StatusWordFields.I;
    case x87SW_C0:
        return (char*) &regd->x87StatusWordFields.C0;
    case x87SW_TOP:
        return (char*) &regd->x87StatusWordFields.TOP;

    case MxCsr:
        return (char*) &regd->regcontext.MxCsr;

    case MxCsr_FZ:
        return (char*) &regd->MxCsrFields.FZ;
    case MxCsr_PM:
        return (char*) &regd->MxCsrFields.PM;
    case MxCsr_UM:
        return (char*) &regd->MxCsrFields.UM;
    case MxCsr_OM:
        return (char*) &regd->MxCsrFields.OM;
    case MxCsr_ZM:
        return (char*) &regd->MxCsrFields.ZM;
    case MxCsr_IM:
        return (char*) &regd->MxCsrFields.IM;
    case MxCsr_DM:
        return (char*) &regd->MxCsrFields.DM;
    case MxCsr_DAZ:
        return (char*) &regd->MxCsrFields.DAZ;
    case MxCsr_PE:
        return (char*) &regd->MxCsrFields.PE;
    case MxCsr_UE:
        return (char*) &regd->MxCsrFields.UE;
    case MxCsr_OE:
        return (char*) &regd->MxCsrFields.OE;
    case MxCsr_ZE:
        return (char*) &regd->MxCsrFields.ZE;
    case MxCsr_DE:
        return (char*) &regd->MxCsrFields.DE;
    case MxCsr_IE:
        return (char*) &regd->MxCsrFields.IE;
    case MxCsr_RC:
        return (char*) &regd->MxCsrFields.RC;

    case XMM0:
        return (char*) &regd->regcontext.XmmRegisters[0];
    case XMM1:
        return (char*) &regd->regcontext.XmmRegisters[1];
    case XMM2:
        return (char*) &regd->regcontext.XmmRegisters[2];
    case XMM3:
        return (char*) &regd->regcontext.XmmRegisters[3];
    case XMM4:
        return (char*) &regd->regcontext.XmmRegisters[4];
    case XMM5:
        return (char*) &regd->regcontext.XmmRegisters[5];
    case XMM6:
        return (char*) &regd->regcontext.XmmRegisters[6];
    case XMM7:
        return (char*) &regd->regcontext.XmmRegisters[7];
#ifdef _WIN64
    case XMM8:
        return (char*) &regd->regcontext.XmmRegisters[8];
    case XMM9:
        return (char*) &regd->regcontext.XmmRegisters[9];
    case XMM10:
        return (char*) &regd->regcontext.XmmRegisters[10];
    case XMM11:
        return (char*) &regd->regcontext.XmmRegisters[11];
    case XMM12:
        return (char*) &regd->regcontext.XmmRegisters[12];
    case XMM13:
        return (char*) &regd->regcontext.XmmRegisters[13];
    case XMM14:
        return (char*) &regd->regcontext.XmmRegisters[14];
    case XMM15:
        return (char*) &regd->regcontext.XmmRegisters[15];
#endif  //_WIN64

    case YMM0:
        return (char*) &regd->regcontext.YmmRegisters[0];
    case YMM1:
        return (char*) &regd->regcontext.YmmRegisters[1];
    case YMM2:
        return (char*) &regd->regcontext.YmmRegisters[2];
    case YMM3:
        return (char*) &regd->regcontext.YmmRegisters[3];
    case YMM4:
        return (char*) &regd->regcontext.YmmRegisters[4];
    case YMM5:
        return (char*) &regd->regcontext.YmmRegisters[5];
    case YMM6:
        return (char*) &regd->regcontext.YmmRegisters[6];
    case YMM7:
        return (char*) &regd->regcontext.YmmRegisters[7];
#ifdef _WIN64
    case YMM8:
        return (char*) &regd->regcontext.YmmRegisters[8];
    case YMM9:
        return (char*) &regd->regcontext.YmmRegisters[9];
    case YMM10:
        return (char*) &regd->regcontext.YmmRegisters[10];
    case YMM11:
        return (char*) &regd->regcontext.YmmRegisters[11];
    case YMM12:
        return (char*) &regd->regcontext.YmmRegisters[12];
    case YMM13:
        return (char*) &regd->regcontext.YmmRegisters[13];
    case YMM14:
        return (char*) &regd->regcontext.YmmRegisters[14];
    case YMM15:
        return (char*) &regd->regcontext.YmmRegisters[15];
#endif  //_WIN64
    }
#else
  const REGDUMPA64* regd = (REGDUMPA64*)regdraw;
  switch (reg) {
    case FLAGS:
      return (char*)&regd->flags;
    case N:
      return (char*)&regd->n;
    case Z:
      return (char*)&regd->z;
    case C:
      return (char*)&regd->c;
    case V:
      return (char*)&regd->v;
    default:
      break;
  }
  if (reg < LR) return (char*)&regd->regcontext.gpr[reg];
  if (reg == LR) return (char*)&regd->regcontext.clr;
  if (reg == SP) return (char*)&regd->regcontext.csp;
  if (reg == PC) return (char*)&regd->regcontext.cip;
  if (reg >= Q0 && reg < Q0 + 32)
    return (char*)&regd->regcontext.neon[reg - Q0][0];
#endif

  return (char*)&null_value;
}

void RegistersViewA64::setRegisters(REGDUMP* regraw) {
  // tests if new-register-value == old-register-value holds
  REGDUMPA64* reg = (REGDUMPA64*)regraw;
  if (mCip != reg->regcontext.cip)  // CIP changed
  {
    wCipRegDumpStruct = wRegDumpStruct;
    mRegisterUpdates.clear();
    mCip = reg->regcontext.cip;
  }

  // iterate all ids (CAX, CBX, ...)
  for (auto itr = mRegisterMapping.begin(); itr != mRegisterMapping.end();
       itr++) {
    if (CompareRegisters(itr.key(), reg, &wCipRegDumpStruct) != 0)
      mRegisterUpdates.insert(itr.key());
    else if (mRegisterUpdates.contains(itr.key()))  // registers are equal
      mRegisterUpdates.remove(itr.key());
  }

  // now we can save the values
  wRegDumpStruct = (*reg);

  if (mCip != reg->regcontext.cip) wCipRegDumpStruct = wRegDumpStruct;

  // force repaint
  emit refresh();
}

void RegistersViewA64::ensureRegisterVisible(REGISTER_NAME reg) {
  QScrollArea* upperScrollArea =
      (QScrollArea*)this->parentWidget()->parentWidget();

  int ySpace = yTopSpacing;
  if (mVScrollOffset != 0) ySpace = 0;
  int y = mRowHeight * (mRegisterPlaces[reg].line + mVScrollOffset) + ySpace;

  upperScrollArea->ensureVisible(0, y);
}
